SensorManager.java revision 050b56244ff46d43e4886018d7cd20f0b1dc02b9
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.Looper;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseArray;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IRotationWatcher;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowManager;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Surface;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collections;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
3774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * SensorManager lets you access the device's {@link android.hardware.Sensor
3874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * sensors}. Get an instance of this class by calling
3974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * {@link android.content.Context#getSystemService(java.lang.String)
4074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * Context.getSystemService()} with the argument
4174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * {@link android.content.Context#SENSOR_SERVICE}.
420f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
430f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * <pre class="prettyprint">
440f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * public class SensorActivity extends Activity, implements SensorEventListener {
450f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     private final SensorManager mSensorManager;
460f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     private final Sensor mAccelerometer;
470f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
480f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     public SensorActivity() {
490f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *         mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
500f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *         mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
510f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *         mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
520f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     }
530f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
540f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     public void onAccuracyChanged(Sensor sensor, int accuracy) {
550f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     }
560f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
570f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     public abstract void onSensorChanged(SensorEvent event) {
580f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     }
590f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * }
600f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * </pre>
610f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
620f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * @see SensorEventListener
630f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * @see SensorEvent
640f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * @see Sensor
650f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
67287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopianpublic class SensorManager
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "SensorManager";
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final float[] mTempMatrix = new float[16];
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* NOTE: sensor IDs must be a power of 2 */
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an orientation sensor. See
7674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
770f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ORIENTATION = 1 << 0;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an accelerometer. See
8574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
860f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ACCELEROMETER = 1 << 1;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a temperature sensor See
9474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
950f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_TEMPERATURE = 1 << 2;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a magnetic sensor See
10374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1040f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MAGNETIC_FIELD = 1 << 3;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an ambient light sensor See
11274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1130f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_LIGHT = 1 << 4;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a proximity sensor See
12174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1220f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_PROXIMITY = 1 << 5;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a Tricorder See
13074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1310f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_TRICORDER = 1 << 6;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an orientation sensor. See
13974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1400f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
14774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant that includes all sensors
1480f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1494a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1504a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ALL = 0x7F;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
15574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Smallest sensor ID
1560f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1574a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1584a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MIN = SENSOR_ORIENTATION;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
16374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Largest sensor ID
1640f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1654a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1664a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1);
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
17274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the X value in the array returned by
1734a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
1740f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1754a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1764a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DATA_X = 0;
17974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
18074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
18174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the Y value in the array returned by
1824a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
1830f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1844a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1854a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DATA_Y = 1;
18874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
18974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
19074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the Z value in the array returned by
1914a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
1920f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1934a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1944a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DATA_Z = 2;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
19974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Offset to the untransformed values in the array returned by
2004a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2010f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2024a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2034a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_INDEX = 3;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
20874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed X value in the array returned by
2094a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2100f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2114a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2124a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_X = 3;
21574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
21674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
21774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed Y value in the array returned by
2184a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2190f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2204a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2214a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_Y = 4;
22474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
22574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
22674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed Z value in the array returned by
2274a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2280f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2294a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2304a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_Z = 5;
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Standard gravity (g) on Earth. This value is equivalent to 1G */
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float STANDARD_GRAVITY = 9.80665f;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Sun's gravity in SI units (m/s^2) */
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_SUN             = 275.0f;
23974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Mercury's gravity in SI units (m/s^2) */
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MERCURY         = 3.70f;
24174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Venus' gravity in SI units (m/s^2) */
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_VENUS           = 8.87f;
24374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Earth's gravity in SI units (m/s^2) */
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_EARTH           = 9.80665f;
24574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** The Moon's gravity in SI units (m/s^2) */
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MOON            = 1.6f;
24774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Mars' gravity in SI units (m/s^2) */
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MARS            = 3.71f;
24974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Jupiter's gravity in SI units (m/s^2) */
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_JUPITER         = 23.12f;
25174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Saturn's gravity in SI units (m/s^2) */
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_SATURN          = 8.96f;
25374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Uranus' gravity in SI units (m/s^2) */
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_URANUS          = 8.69f;
25574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Neptune's gravity in SI units (m/s^2) */
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_NEPTUNE         = 11.0f;
25774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Pluto's gravity in SI units (m/s^2) */
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_PLUTO           = 0.6f;
25974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_DEATH_STAR_I    = 0.000000353036145f;
26174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Gravity on the island */
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_THE_ISLAND      = 4.815162342f;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Maximum magnetic field on Earth's surface */
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f;
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Minimum magnetic field on Earth's surface */
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2700f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian
27174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Maximum luminance of sunlight in lux */
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
27374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance of sunlight in lux */
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNLIGHT     = 110000.0f;
27574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance in shade in lux */
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SHADE        = 20000.0f;
27774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance under an overcast sky in lux */
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_OVERCAST     = 10000.0f;
27974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at sunrise in lux */
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNRISE      = 400.0f;
28174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance under a cloudy sky in lux */
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_CLOUDY       = 100.0f;
28374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at night with full moon in lux */
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_FULLMOON     = 0.25f;
28574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at night with no moon in lux*/
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_NO_MOON      = 0.001f;
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2880f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** get sensor data as fast as possible */
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_FASTEST = 0;
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate suitable for games */
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_GAME = 1;
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate suitable for the user interface  */
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_UI = 2;
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate (default) suitable for screen orientation changes */
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_NORMAL = 3;
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
30074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The values returned by this sensor cannot be trusted, calibration is
30174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * needed or the environment doesn't allow readings
30274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_UNRELIABLE = 0;
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
30674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This sensor is reporting data with low accuracy, calibration with the
30774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * environment is needed
30874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
31174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
31274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This sensor is reporting data with an average level of accuracy,
31374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * calibration with the environment may improve the readings
31474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** This sensor is reporting data with maximum accuracy */
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_X = 1;
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_Y = 2;
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_Z = 3;
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_X = AXIS_X | 0x80;
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_Y = AXIS_Y | 0x80;
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_Z = AXIS_Z | 0x80;
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Looper mMainLooper;
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("deprecation")
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<SensorListener, LegacyListener> mLegacyListenersMap =
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<SensorListener, LegacyListener>();
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int SENSOR_DISABLE = -1;
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean sSensorModuleInitialized = false;
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static SparseArray<List<Sensor>> sSensorListByType = new SparseArray<List<Sensor>>();
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static IWindowManager sWindowManager;
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int sRotation = Surface.ROTATION_0;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* The thread and the sensor list are global to the process
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * but the actual thread is spawned on demand */
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static SensorThread sSensorThread;
3511bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    private static int sQueue;
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Used within this module from outside SensorManager, don't make private
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final ArrayList<ListenerDelegate> sListeners =
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new ArrayList<ListenerDelegate>();
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static private class SensorThread {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Thread mThread;
363b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian        boolean mSensorsReady;
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SensorThread() {
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected void finalize() {
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // must be called with sListeners lock
3731bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        boolean startLocked() {
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mThread == null) {
3761bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    mSensorsReady = false;
3771bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    SensorThreadRunnable runnable = new SensorThreadRunnable();
3781bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    Thread thread = new Thread(runnable, SensorThread.class.getName());
3791bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    thread.start();
3801bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    synchronized (runnable) {
3811bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                        while (mSensorsReady == false) {
3821bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                            runnable.wait();
383b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                        }
384b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                    }
3851bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    mThread = thread;
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
387b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian            } catch (InterruptedException e) {
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
389b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian            return mThread == null ? false : true;
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private class SensorThreadRunnable implements Runnable {
3931bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            SensorThreadRunnable() {
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
395270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood
396270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood            private boolean open() {
397b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                // NOTE: this cannot synchronize on sListeners, since
398b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                // it's held in the main thread at least until we
399b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                // return from here.
4001bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                sQueue = sensors_create_queue();
401270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                return true;
402270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood            }
403270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public void run() {
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //Log.d(TAG, "entering main sensor thread");
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float[] values = new float[3];
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int[] status = new int[1];
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final long timestamp[] = new long[1];
409e417158c06c81c8c4dc6794c5421b711e671c7e3Mathias Agopian                Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
411270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                if (!open()) {
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return;
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
415b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                synchronized (this) {
416b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                    // we've open the driver, we're ready to open the sensors
417b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                    mSensorsReady = true;
418b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                    this.notify();
419b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                }
420b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while (true) {
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // wait for an event
4231bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    final int sensor = sensors_data_poll(sQueue, values, status, timestamp);
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    int accuracy = status[0];
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (sListeners) {
4276dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                        if (sensor == -1 || sListeners.isEmpty()) {
4286dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                            if (sensor == -1) {
4296dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                                // we lost the connection to the event stream. this happens
4306dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                                // when the last listener is removed.
4316dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                                Log.d(TAG, "_sensors_data_poll() failed, we bail out.");
4326dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                            }
4336dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber
4346dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                            // we have no more listeners or polling failed, terminate the thread
4351bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                            sensors_destroy_queue(sQueue);
4361bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                            sQueue = 0;
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mThread = null;
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            break;
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        final Sensor sensorObject = sHandleToSensor.get(sensor);
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (sensorObject != null) {
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // report the sensor event to all listeners that
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // care about it.
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            final int size = sListeners.size();
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            for (int i=0 ; i<size ; i++) {
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                ListenerDelegate listener = sListeners.get(i);
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (listener.hasSensor(sensorObject)) {
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    // this is asynchronous (okay to call
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    // with sListeners lock held).
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    listener.onSensorChangedLocked(sensorObject,
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            values, timestamp, accuracy);
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //Log.d(TAG, "exiting main sensor thread");
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4641bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    private class ListenerDelegate {
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final SensorEventListener mSensorEventListener;
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final Handler mHandler;
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private SensorEvent mValuesPool;
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int mSensors;
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) {
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensorEventListener = listener;
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // currently we create one Handler instance per listener, but we could
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // have one per looper (we'd need to pass the ListenerDelegate
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // instance to handleMessage and keep track of them separately).
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler = new Handler(looper) {
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                @Override
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                public void handleMessage(Message msg) {
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SensorEvent t = (SensorEvent)msg.obj;
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.accuracy >= 0) {
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy);
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mSensorEventListener.onSensorChanged(t);
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    returnToPool(t);
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            };
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            addSensor(sensor);
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected SensorEvent createSensorEvent() {
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // maximal size for all legacy events is 3
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new SensorEvent(3);
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected SensorEvent getFromPool() {
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorEvent t = null;
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // remove the array from the pool
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                t = mValuesPool;
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mValuesPool = null;
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (t == null) {
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // the pool was empty, we need a new one
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                t = createSensorEvent();
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return t;
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected void returnToPool(SensorEvent t) {
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // put back the array into the pool
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mValuesPool == null) {
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mValuesPool = t;
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Object getListener() {
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSensorEventListener;
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int addSensor(Sensor sensor) {
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors |= 1<<sensor.getHandle();
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensorList.add(sensor);
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSensors;
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int removeSensor(Sensor sensor) {
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors &= ~(1<<sensor.getHandle());
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensorList.remove(sensor);
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSensors;
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean hasSensor(Sensor sensor) {
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ((mSensors & (1<<sensor.getHandle())) != 0);
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> getSensors() {
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSensorList;
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void onSensorChangedLocked(Sensor sensor, float[] values, long[] timestamp, int accuracy) {
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorEvent t = getFromPool();
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float[] v = t.values;
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[0] = values[0];
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[1] = values[1];
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[2] = values[2];
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.timestamp = timestamp[0];
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.accuracy = accuracy;
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.sensor = sensor;
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Message msg = Message.obtain();
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            msg.what = 0;
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            msg.obj = t;
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler.sendMessage(msg);
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SensorManager(Looper mainLooper) {
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMainLooper = mainLooper;
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(sListeners) {
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!sSensorModuleInitialized) {
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sSensorModuleInitialized = true;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                nativeClassInit();
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sWindowManager = IWindowManager.Stub.asInterface(
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ServiceManager.getService("window"));
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (sWindowManager != null) {
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // if it's null we're running in the system process
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // which won't get the rotated values
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
575287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                        sRotation = sWindowManager.watchRotation(
576287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                            new IRotationWatcher.Stub() {
577287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                                public void onRotationChanged(int rotation) {
578287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                                    SensorManager.this.onRotationChanged(rotation);
579287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                                }
580287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                            }
581287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                        );
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // initialize the sensor list
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sensors_module_init();
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final ArrayList<Sensor> fullList = sFullSensorsList;
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int i = 0;
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Sensor sensor = new Sensor();
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i = sensors_module_get_next_sensor(sensor, i);
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (i>=0) {
595f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato                        //Log.d(TAG, "found sensor: " + sensor.getName() +
596f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato                        //        ", handle=" + sensor.getHandle());
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sensor.setLegacyType(getLegacySensorType(sensor.getType()));
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fullList.add(sensor);
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sHandleToSensor.append(sensor.getHandle(), sensor);
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } while (i>0);
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sSensorThread = new SensorThread();
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getLegacySensorType(int type) {
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (type) {
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_ACCELEROMETER:
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_ACCELEROMETER;
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_MAGNETIC_FIELD:
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_MAGNETIC_FIELD;
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_ORIENTATION:
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_ORIENTATION_RAW;
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_TEMPERATURE:
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_TEMPERATURE;
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
62274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
62374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return available sensors.
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
62574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#getSensorList(int)} instead
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getSensors() {
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int result = 0;
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ArrayList<Sensor> fullList = sFullSensorsList;
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (Sensor i : fullList) {
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (i.getType()) {
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_ACCELEROMETER:
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_ACCELEROMETER;
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_MAGNETIC_FIELD:
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_MAGNETIC_FIELD;
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_ORIENTATION:
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_ORIENTATION |
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    SensorManager.SENSOR_ORIENTATION_RAW;
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
64974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Use this method to get the list of available sensors of a certain type.
65074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Make multiple calls to get sensors of different types or use
65174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the
65274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * sensors.
6530f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
65474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param type
65574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        of sensors requested
6560f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a list of sensors matching the asked type.
6580f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
6590f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getDefaultSensor(int)
6600f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see Sensor
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<Sensor> getSensorList(int type) {
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // cache the returned lists the first time
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> list;
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ArrayList<Sensor> fullList = sFullSensorsList;
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(fullList) {
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            list = sSensorListByType.get(type);
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (list == null) {
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (type == Sensor.TYPE_ALL) {
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    list = fullList;
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    list = new ArrayList<Sensor>();
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (Sensor i : fullList) {
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (i.getType() == type)
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            list.add(i);
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                list = Collections.unmodifiableList(list);
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sSensorListByType.append(type, list);
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return list;
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
68674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Use this method to get the default sensor for a given type. Note that the
68774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * returned sensor could be a composite sensor, and its data could be
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * averaged or filtered. If you need to access the raw sensors use
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link SensorManager#getSensorList(int) getSensorList}.
6900f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
69174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param type
69274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        of sensors requested
6930f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the default sensors matching the asked type.
6950f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
6960f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getSensorList(int)
6970f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see Sensor
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Sensor getDefaultSensor(int type) {
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: need to be smarter, for now, just return the 1st sensor
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> l = getSensorList(type);
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return l.isEmpty() ? null : l.get(0);
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registers a listener for given sensors.
7070f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
70974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
71074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
7110f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
71274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
71374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        sensor listener object
7140f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
71574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensors
71674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a bit masks of the sensors to register to
7170f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
71874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> if the sensor is supported and successfully
71974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorListener listener, int sensors) {
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registers a SensorListener for given sensors.
7280f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
73074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
73174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
7320f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
73374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
73474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        sensor listener object
7350f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
73674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensors
73774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a bit masks of the sensors to register to
7380f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
73974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param rate
74074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        rate of events. This is only a hint to the system. events may be
74174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
74274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
74374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
74474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
7450f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
74674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> if the sensor is supported and successfully
74774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorListener listener, int sensors, int rate) {
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result = false;
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("deprecation")
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean registerLegacyListener(int legacyType, int type,
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorListener listener, int sensors, int rate)
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result = false;
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Are we activating this legacy sensor?
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((sensors & legacyType) != 0) {
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // if so, find a suitable Sensor
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Sensor sensor = getDefaultSensor(type);
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sensor != null) {
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If we don't already have one, create a LegacyListener
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // to wrap this listener and process the events as
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // they are expected by legacy apps.
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                LegacyListener legacyListener = null;
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                synchronized (mLegacyListenersMap) {
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    legacyListener = mLegacyListenersMap.get(listener);
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (legacyListener == null) {
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // we didn't find a LegacyListener for this client,
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // create one, and put it in our list.
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        legacyListener = new LegacyListener(listener);
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mLegacyListenersMap.put(listener, legacyListener);
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // register this legacy sensor with this legacy listener
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                legacyListener.registerSensor(legacyType);
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // and finally, register the legacy listener with the new apis
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                result = registerListener(legacyListener, sensor, rate);
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for the sensors with which it is registered.
8050f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
80774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#unregisterListener(SensorEventListener, Sensor)}
80874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
8090f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
81074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
81174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
8120f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
81374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensors
81474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a bit masks of the sensors to unregister from
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorListener listener, int sensors) {
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("deprecation")
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void unregisterLegacyListener(int legacyType, int type,
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorListener listener, int sensors)
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // do we know about this listener?
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LegacyListener legacyListener = null;
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mLegacyListenersMap) {
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            legacyListener = mLegacyListenersMap.get(listener);
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (legacyListener != null) {
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Are we deactivating this legacy sensor?
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((sensors & legacyType) != 0) {
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // if so, find the corresponding Sensor
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Sensor sensor = getDefaultSensor(type);
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (sensor != null) {
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // unregister this legacy sensor and if we don't
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // need the corresponding Sensor, unregister it too
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (legacyListener.unregisterSensor(legacyType)) {
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // corresponding sensor not needed, unregister
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        unregisterListener(legacyListener, sensor);
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // finally check if we still need the legacyListener
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // in our mapping, if not, get rid of it too.
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        synchronized(sListeners) {
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            boolean found = false;
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            for (ListenerDelegate i : sListeners) {
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (i.getListener() == legacyListener) {
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    found = true;
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    break;
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (!found) {
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                synchronized (mLegacyListenersMap) {
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    mLegacyListenersMap.remove(listener);
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for all sensors.
8770f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
87974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#unregisterListener(SensorEventListener)}
88074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
8810f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
88274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
88374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorListener listener) {
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for the sensors with which it is registered.
8920f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
89374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
89474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorEventListener object
8950f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
89674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
89774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the sensor to unregister from
8980f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8990f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener)
9000f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int)
9010f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorEventListener listener, Sensor sensor) {
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterListener((Object)listener, sensor);
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for all sensors.
9090f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
91074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
91174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
9120f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9130f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener, Sensor)
9140f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int)
9150f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorEventListener listener) {
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterListener((Object)listener);
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
92274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Registers a {@link android.hardware.SensorEventListener
92374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * SensorEventListener} for the given sensor.
9240f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
92574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
92674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        A {@link android.hardware.SensorEventListener SensorEventListener}
92774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        object.
9280f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
92974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
93074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.hardware.Sensor Sensor} to register to.
9310f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
93274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param rate
93374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The rate {@link android.hardware.SensorEvent sensor events} are
93474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered at. This is only a hint to the system. Events may be
93574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
93674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
93774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
938050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}
939050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian     *        or, the desired delay between events in microsecond.
9400f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
94174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> if the sensor is supported and successfully
94274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled.
9430f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9440f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int, Handler)
9450f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener)
9460f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener, Sensor)
9470f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return registerListener(listener, sensor, rate, null);
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
95474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Registers a {@link android.hardware.SensorEventListener
95574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * SensorEventListener} for the given sensor.
9560f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
95774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
95874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        A {@link android.hardware.SensorEventListener SensorEventListener}
95974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        object.
9600f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
96174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
96274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.hardware.Sensor Sensor} to register to.
9630f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
96474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param rate
96574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The rate {@link android.hardware.SensorEvent sensor events} are
96674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered at. This is only a hint to the system. Events may be
96774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
96874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
96974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
97074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
971050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian     *        or, the desired delay between events in microsecond.
9720f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
97374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param handler
97474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.os.Handler Handler} the
97574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent sensor events} will be
97674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered to.
9770f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the sensor is supported and successfully enabled.
9790f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9800f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int)
9810f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener)
9820f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener, Sensor)
9830f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Handler handler) {
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null || sensor == null) {
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result;
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int delay = -1;
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (rate) {
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_FASTEST:
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delay = 0;
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_GAME:
997050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian                delay = 20000;
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_UI:
1000050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian                delay = 60000;
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_NORMAL:
1003050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian                delay = 200000;
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
1006050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian                delay = rate;
1007050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian                break;
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10101bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        synchronized (sListeners) {
10111bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            ListenerDelegate l = null;
10121bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            for (ListenerDelegate i : sListeners) {
10131bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                if (i.getListener() == listener) {
10141bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    l = i;
10151bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    break;
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10171bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            }
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10191bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            String name = sensor.getName();
10201bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            int handle = sensor.getHandle();
10211bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            if (l == null) {
10221bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                result = false;
10231bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                l = new ListenerDelegate(listener, sensor, handler);
10241bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                sListeners.add(l);
10251bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                if (!sListeners.isEmpty()) {
10261bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    result = sSensorThread.startLocked();
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (result) {
10281bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                        result = sensors_enable_sensor(sQueue, name, handle, delay);
10291bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                        if (!result) {
10301bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                            // there was an error, remove the listeners
10311bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                            sListeners.remove(l);
10321bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                        }
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10351bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            } else {
10361bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                result = sensors_enable_sensor(sQueue, name, handle, delay);
10371bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                if (result) {
10381bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    l.addSensor(sensor);
10391bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                }
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void unregisterListener(Object listener, Sensor sensor) {
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null || sensor == null) {
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10491bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        synchronized (sListeners) {
10501bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            final int size = sListeners.size();
10511bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            for (int i=0 ; i<size ; i++) {
10521bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                ListenerDelegate l = sListeners.get(i);
10531bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                if (l.getListener() == listener) {
10541bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    // disable these sensors
10551bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    String name = sensor.getName();
10561bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    int handle = sensor.getHandle();
10571bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
10581bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    // if we have no more sensors enabled on this listener,
10591bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    // take it off the list.
10601bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    if (l.removeSensor(sensor) == 0) {
10611bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                        sListeners.remove(i);
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10631bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    break;
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void unregisterListener(Object listener) {
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10731bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        synchronized (sListeners) {
10741bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            final int size = sListeners.size();
10751bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            for (int i=0 ; i<size ; i++) {
10761bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                ListenerDelegate l = sListeners.get(i);
10771bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                if (l.getListener() == listener) {
10781bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    // disable all sensors for this listener
10791bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    for (Sensor sensor : l.getSensors()) {
10801bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                        String name = sensor.getName();
10811bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                        int handle = sensor.getHandle();
10821bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                        sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10841bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    sListeners.remove(i);
10851bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    break;
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
109274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
109374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Computes the inclination matrix <b>I</b> as well as the rotation matrix
109474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>R</b> transforming a vector from the device coordinate system to the
109574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * world's coordinate system which is defined as a direct orthonormal basis,
109674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * where:
109774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
10980f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
109974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the ground at the device's current location and roughly points East).</li>
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Y is tangential to the ground at the device's current location and
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * points towards the magnetic North Pole.</li>
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Z points towards the sky and is perpendicular to the ground.</li>
110574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
11060f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
11070f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * <p>
11080f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * <center><img src="../../../images/axis_globe.png"
11090f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * alt="Sensors coordinate-system diagram." border="0" /></center>
11100f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * </p>
11110f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
111474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
111574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * By definition:
111674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
111774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * [0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity)
111874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
111974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * [0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b> (m = magnitude of
112074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * geomagnetic field)
112174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
112274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>R</b> is the identity matrix when the device is aligned with the
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * world's coordinate system, that is, when the device's X axis points
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * toward East, the Y axis points to the North Pole and the device is facing
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the sky.
11260f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
112774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
112874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>I</b> is a rotation matrix transforming the geomagnetic vector into
112974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * the same coordinate space as gravity (the world's coordinate space).
113074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>I</b> is a simple rotation around the X axis. The inclination angle in
113174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * radians can be computed with {@link #getInclination}.
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
11330f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
113474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
113574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Each matrix is returned either as a 3x3 or 4x4 row-major matrix depending
113674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * on the length of the passed array:
113774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
113874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>If the array length is 16:</u>
11390f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]   M[ 3]  \
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 4]   M[ 5]   M[ 6]   M[ 7]  |
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 8]   M[ 9]   M[10]   M[11]  |
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \  M[12]   M[13]   M[14]   M[15]  /
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
11460f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
114774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This matrix is ready to be used by OpenGL ES's
114874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int)
114974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * glLoadMatrixf(float[], int)}.
115074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
115174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Note that because OpenGL matrices are column-major matrices you must
115274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * transpose the matrix before using it. However, since the matrix is a
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rotation matrix, its transpose is also its inverse, conveniently, it is
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * often the inverse of the rotation that is needed for rendering; it can
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * therefore be used with OpenGL ES directly.
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Also note that the returned matrices always have this form:
11580f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]   0  \
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 4]   M[ 5]   M[ 6]   0  |
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 8]   M[ 9]   M[10]   0  |
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \      0       0       0   1  /
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
11650f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
116674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
116774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>If the array length is 9:</u>
11680f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]  \
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 3]   M[ 4]   M[ 5]  |
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \  M[ 6]   M[ 7]   M[ 8]  /
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
11740f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
117674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
117774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The inverse of each matrix can be computed easily by taking its
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * transpose.
11790f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
118074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
118174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The matrices returned by this function are meaningful only when the
118274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * device is not free-falling and it is not close to the magnetic north. If
118374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * the device is accelerating, or placed into a strong magnetic field, the
118474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * returned matrices may be inaccurate.
11850f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
118674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param R
118774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 9 floats holding the rotation matrix <b>R</b> when
118874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        this function returns. R can be null.
118974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
11900f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
119174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param I
119274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 9 floats holding the rotation matrix <b>I</b> when
119374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        this function returns. I can be null.
119474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
11950f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
119674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param gravity
119774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 3 floats containing the gravity vector expressed in
119874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the device's coordinate. You can simply use the
119974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent#values values} returned by a
120074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent SensorEvent} of a
120174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor Sensor} of type
120274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor#TYPE_ACCELEROMETER
120374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        TYPE_ACCELEROMETER}.
120474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
12050f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
120674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param geomagnetic
120774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 3 floats containing the geomagnetic vector
120874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        expressed in the device's coordinate. You can simply use the
120974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent#values values} returned by a
121074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent SensorEvent} of a
121174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor Sensor} of type
121274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD
121374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        TYPE_MAGNETIC_FIELD}.
12140f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
121574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> on success, <code>false</code> on failure (for
121674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         instance, if the device is in free fall). On failure the output
121774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         matrices are not modified.
12180f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
12190f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getInclination(float[])
12200f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getOrientation(float[], float[])
12210f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #remapCoordinateSystem(float[], int, int, float[])
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean getRotationMatrix(float[] R, float[] I,
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] gravity, float[] geomagnetic) {
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: move this to native code for efficiency
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Ax = gravity[0];
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Ay = gravity[1];
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Az = gravity[2];
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ex = geomagnetic[0];
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ey = geomagnetic[1];
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ez = geomagnetic[2];
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hx = Ey*Az - Ez*Ay;
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hy = Ez*Ax - Ex*Az;
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hz = Ex*Ay - Ey*Ax;
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (normH < 0.1f) {
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // device is close to free fall (or in space?), or close to
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // magnetic north pole. Typical values are  > 100.
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float invH = 1.0f / normH;
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hx *= invH;
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hy *= invH;
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hz *= invH;
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Ax *= invA;
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Ay *= invA;
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Az *= invA;
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Mx = Ay*Hz - Az*Hy;
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float My = Az*Hx - Ax*Hz;
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Mz = Ax*Hy - Ay*Hx;
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (R != null) {
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (R.length == 9) {
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[0] = Hx;     R[1] = Hy;     R[2] = Hz;
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[3] = Mx;     R[4] = My;     R[5] = Mz;
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[6] = Ax;     R[7] = Ay;     R[8] = Az;
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (R.length == 16) {
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[0]  = Hx;    R[1]  = Hy;    R[2]  = Hz;   R[3]  = 0;
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[4]  = Mx;    R[5]  = My;    R[6]  = Mz;   R[7]  = 0;
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[8]  = Ax;    R[9]  = Ay;    R[10] = Az;   R[11] = 0;
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[12] = 0;     R[13] = 0;     R[14] = 0;    R[15] = 1;
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (I != null) {
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // compute the inclination matrix by projecting the geomagnetic
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // vector onto the Z (gravity) and X (horizontal component
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // of geomagnetic vector) axes.
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (I.length == 9) {
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[0] = 1;     I[1] = 0;     I[2] = 0;
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[3] = 0;     I[4] = c;     I[5] = s;
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[6] = 0;     I[7] =-s;     I[8] = c;
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (I.length == 16) {
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[0] = 1;     I[1] = 0;     I[2] = 0;
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[4] = 0;     I[5] = c;     I[6] = s;
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[8] = 0;     I[9] =-s;     I[10]= c;
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[15] = 1;
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes the geomagnetic inclination angle in radians from the
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}.
12900f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
129174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param I
129274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        inclination matrix see {@link #getRotationMatrix}.
12930f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The geomagnetic inclination angle in radians.
12950f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
12960f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getRotationMatrix(float[], float[], float[], float[])
12970f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getOrientation(float[], float[])
12980f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see GeomagneticField
12990f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static float getInclination(float[] I) {
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (I.length == 9) {
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (float)Math.atan2(I[5], I[4]);
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
13050f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian            return (float)Math.atan2(I[6], I[5]);
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
131074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
131174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Rotates the supplied rotation matrix so it is expressed in a different
131274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * coordinate system. This is typically used when an application needs to
131374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * compute the three orientation angles of the device (see
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getOrientation}) in a different coordinate system.
131574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
13160f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
131774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
131874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * When the rotation matrix is used for drawing (for instance with OpenGL
131974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * ES), it usually <b>doesn't need</b> to be transformed by this function,
132074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * unless the screen is physically rotated, in which case you can use
132174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.view.Display#getRotation() Display.getRotation()} to
132274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * retrieve the current rotation of the screen. Note that because the user
132374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * is generally free to rotate their screen, you often should consider the
132474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * rotation in deciding the parameters to use here.
132574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
13260f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
132774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
132874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>Examples:</u>
132974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
13300f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
133174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
133274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <li>Using the camera (Y axis along the camera's axis) for an augmented
133374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * reality application where the rotation angles are needed:</li>
13340f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
133574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
133674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
133774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code>
133874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
133974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
13400f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
13415cb70b54156fb305d579a1cc167424c8705bfdf7Dianne Hackborn     * <li>Using the device as a mechanical compass when rotation is
134274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:</li>
13430f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
134474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
134574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
134674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code>
134774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
134874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
13490f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
135074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Beware of the above example. This call is needed only to account for a
135174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * rotation from its natural orientation when calculating the rotation
135274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * angles (see {@link #getOrientation}). If the rotation matrix is also used
135374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * for rendering, it may not need to be transformed, for instance if your
135474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.app.Activity Activity} is running in landscape mode.
135574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
13560f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
135774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
135874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Since the resulting coordinate system is orthonormal, only two axes need
135974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * to be specified.
13600f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
136174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param inR
136274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the rotation matrix to be transformed. Usually it is the matrix
136374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        returned by {@link #getRotationMatrix}.
13640f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
136574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param X
136674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        defines on which world axis and direction the X axis of the device
136774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is mapped.
13680f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
136974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param Y
137074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        defines on which world axis and direction the Y axis of the device
137174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is mapped.
13720f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
137374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param outR
137474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the transformed rotation matrix. inR and outR can be the same
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        array, but it is not recommended for performance reason.
13760f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
137774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> on success. <code>false</code> if the input
137874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         parameters are incorrect, for instance if X and Y define the same
137974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         axis. Or if inR and outR don't have the same length.
13800f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
13810f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getRotationMatrix(float[], float[], float[], float[])
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean remapCoordinateSystem(float[] inR, int X, int Y,
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] outR)
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (inR == outR) {
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float[] temp = mTempMatrix;
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(temp) {
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // we don't expect to have a lot of contention
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final int size = outR.length;
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (int i=0 ; i<size ; i++)
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        outR[i] = temp[i];
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return true;
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return remapCoordinateSystemImpl(inR, X, Y, outR);
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y,
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] outR)
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * X and Y define a rotation matrix 'r':
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *                              r[0] ^ r[1]
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * where the 3rd line is the vector product of the first 2 lines
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int length = outR.length;
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (inR.length != length)
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // invalid parameter
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((X & 0x7C)!=0 || (Y & 0x7C)!=0)
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // invalid parameter
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (((X & 0x3)==0) || ((Y & 0x3)==0))
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // no axis specified
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((X & 0x3) == (Y & 0x3))
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // same axis specified
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // this can be calculated by exclusive-or'ing X and Y; except for
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the sign inversion (+/-) which is calculated below.
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int Z = X ^ Y;
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // extract the axis (remove the sign), offset in the range 0 to 2.
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int x = (X & 0x3)-1;
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int y = (Y & 0x3)-1;
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int z = (Z & 0x3)-1;
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // compute the sign of Z (whether it needs to be inverted)
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int axis_y = (z+1)%3;
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int axis_z = (z+2)%3;
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (((x^axis_y)|(y^axis_z)) != 0)
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Z ^= 0x80;
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sx = (X>=0x80);
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sy = (Y>=0x80);
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sz = (Z>=0x80);
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Perform R * r, in avoiding actual muls and adds.
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int rowLength = ((length==16)?4:3);
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int j=0 ; j<3 ; j++) {
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int offset = j*rowLength;
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0 ; i<3 ; i++) {
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (x==i)   outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0];
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (y==i)   outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1];
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (z==i)   outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2];
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (length == 16) {
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            outR[15] = 1;
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes the device's orientation based on the rotation matrix.
146574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
146674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * When it returns, the array values is filled with the result:
146774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[0]: <i>azimuth</i>, rotation around the Z axis.</li>
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[1]: <i>pitch</i>, rotation around the X axis.</li>
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li>
147174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
14730f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * <center><img src="../../../images/axis_device.png"
14740f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * alt="Sensors coordinate-system diagram." border="0" /></center>
14750f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * </p>
14760f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * <p>
1477210fc914db37b3cf77ebb3bf75b0b509a1ecb07cMathias Agopian     * All three angles above are in <b>radians</b> and <b>positive</b> in the
1478210fc914db37b3cf77ebb3bf75b0b509a1ecb07cMathias Agopian     * <b>counter-clockwise</b> direction.
147974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
148074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param R
148174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        rotation matrix see {@link #getRotationMatrix}.
14820f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
148374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param values
148474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        an array of 3 floats to hold the result.
14850f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The array values passed as argument.
14870f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
14880f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getRotationMatrix(float[], float[], float[], float[])
14890f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see GeomagneticField
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
149174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian   public static float[] getOrientation(float[] R, float values[]) {
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * 4x4 (length=16) case:
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   /  R[ 0]   R[ 1]   R[ 2]   0  \
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 4]   R[ 5]   R[ 6]   0  |
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 8]   R[ 9]   R[10]   0  |
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   \      0       0       0   1  /
14980f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian         *
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * 3x3 (length=9) case:
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   /  R[ 0]   R[ 1]   R[ 2]  \
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 3]   R[ 4]   R[ 5]  |
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   \  R[ 6]   R[ 7]   R[ 8]  /
15030f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian         *
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (R.length == 9) {
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = (float)Math.atan2(R[1], R[4]);
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = (float)Math.asin(-R[7]);
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = (float)Math.atan2(-R[6], R[8]);
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = (float)Math.atan2(R[1], R[5]);
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = (float)Math.asin(-R[9]);
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = (float)Math.atan2(-R[8], R[10]);
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return values;
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onRotationChanged(int rotation) {
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(sListeners) {
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sRotation  = rotation;
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static int getRotation() {
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(sListeners) {
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return sRotation;
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class LegacyListener implements SensorEventListener {
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mValues[] = new float[6];
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private SensorListener mTarget;
15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mSensors;
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final LmsFilter mYawfilter = new LmsFilter();
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LegacyListener(SensorListener target) {
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTarget = target;
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors = 0;
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void registerSensor(int legacyType) {
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors |= legacyType;
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean unregisterSensor(int legacyType) {
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors &= ~legacyType;
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mask = SENSOR_ORIENTATION|SENSOR_ORIENTATION_RAW;
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (((legacyType&mask)!=0) && ((mSensors&mask)!=0)) {
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onAccuracyChanged(Sensor sensor, int accuracy) {
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTarget.onAccuracyChanged(sensor.getLegacyType(), accuracy);
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (AbstractMethodError e) {
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // old app that doesn't implement this method
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // just ignore it.
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onSensorChanged(SensorEvent event) {
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float v[] = mValues;
15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[0] = event.values[0];
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[1] = event.values[1];
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[2] = event.values[2];
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int legacyType = event.sensor.getLegacyType();
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mapSensorDataToWindow(legacyType, v, SensorManager.getRotation());
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mSensors & SENSOR_ORIENTATION_RAW)!=0) {
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTarget.onSensorChanged(SENSOR_ORIENTATION_RAW, v);
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mSensors & SENSOR_ORIENTATION)!=0) {
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    v[0] = mYawfilter.filter(event.timestamp, v[0]);
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTarget.onSensorChanged(SENSOR_ORIENTATION, v);
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTarget.onSensorChanged(legacyType, v);
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Helper function to convert the specified sensor's data to the windows's
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * coordinate space from the device's coordinate space.
15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * output: 3,4,5: values in the old API format
15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *         0,1,2: transformed values in the old API format
15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private void mapSensorDataToWindow(int sensor,
15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float[] values, int orientation) {
16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x = values[0];
16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float y = values[1];
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float z = values[2];
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (sensor) {
16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ORIENTATION:
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ORIENTATION_RAW:
16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    z = -z;
16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ACCELEROMETER:
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x = -x;
16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y = -y;
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    z = -z;
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_MAGNETIC_FIELD:
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x = -x;
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y = -y;
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = x;
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = y;
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = z;
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[3] = x;
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[4] = y;
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[5] = z;
16257895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian
16267895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian            if ((orientation & Surface.ROTATION_90) != 0) {
16277895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                // handles 90 and 270 rotation
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                switch (sensor) {
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ACCELEROMETER:
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_MAGNETIC_FIELD:
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[0] =-y;
16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[1] = x;
16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[2] = z;
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ORIENTATION:
16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ORIENTATION_RAW:
16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[0] = x + ((x < 270) ? 90 : -270);
16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[1] = z;
16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[2] = y;
16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16437895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian            if ((orientation & Surface.ROTATION_180) != 0) {
16447895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                x = values[0];
16457895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                y = values[1];
16467895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                z = values[2];
16477895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                // handles 180 (flip) and 270 (flip + 90) rotation
16487895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                switch (sensor) {
16497895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_ACCELEROMETER:
16507895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_MAGNETIC_FIELD:
16517895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[0] =-x;
16527895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[1] =-y;
16537895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[2] = z;
16547895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        break;
16557895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_ORIENTATION:
16567895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_ORIENTATION_RAW:
16577895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[0] = (x >= 180) ? (x - 180) : (x + 180);
16587895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[1] =-y;
16597895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[2] =-z;
16607895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        break;
16617895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                }
16627895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian            }
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16650f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class LmsFilter {
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final int SENSORS_RATE_MS = 20;
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final int COUNT = 12;
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final float PREDICTION_RATIO = 1.0f/3.0f;
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final float PREDICTION_TIME = (SENSORS_RATE_MS*COUNT/1000.0f)*PREDICTION_RATIO;
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mV[] = new float[COUNT*2];
16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mT[] = new float[COUNT*2];
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mIndex;
16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public LmsFilter() {
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIndex = COUNT;
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public float filter(long time, float in) {
16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float v = in;
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float ns = 1.0f / 1000000000.0f;
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float t = time*ns;
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float v1 = mV[mIndex];
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((v-v1) > 180) {
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                v -= 360;
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if ((v1-v) > 180) {
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                v += 360;
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* Manage the circular buffer, we write the data twice spaced
16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * by COUNT values, so that we don't have to copy the array
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * when it's full
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIndex++;
16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIndex >= COUNT*2)
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mIndex = COUNT;
16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mV[mIndex] = v;
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mT[mIndex] = t;
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mV[mIndex-COUNT] = v;
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mT[mIndex-COUNT] = t;
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float A, B, C, D, E;
17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float a, b;
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int i;
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            A = B = C = D = E = 0;
17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (i=0 ; i<COUNT-1 ; i++) {
17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int j = mIndex - 1 - i;
17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float Z = mV[j];
17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float T = 0.5f*(mT[j] + mT[j+1]) - t;
17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float dT = mT[j] - mT[j+1];
17119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dT *= dT;
17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                A += Z*dT;
17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                B += T*(T*dT);
17149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                C +=   (T*dT);
17159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                D += Z*(T*dT);
17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                E += dT;
17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            b = (A*B + C*D) / (E*B + C*C);
17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            a = (E*b - A) / C;
17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float f = b + PREDICTION_TIME*a;
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Normalize
17239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f *= (1.0f / 360.0f);
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (((f>=0)?f:-f) >= 0.5f)
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                f = f - (float)Math.ceil(f + 0.5f) + 1.0f;
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (f < 0)
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                f += 1.0f;
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f *= 360.0f;
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return f;
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17330f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void nativeClassInit();
17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native int sensors_module_init();
17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native int sensors_module_get_next_sensor(Sensor sensor, int next);
17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Used within this module from outside SensorManager, don't make private
17401bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    static native int sensors_create_queue();
17411bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    static native void sensors_destroy_queue(int queue);
17421bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    static native boolean sensors_enable_sensor(int queue, String name, int sensor, int enable);
17431bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    static native int sensors_data_poll(int queue, float[] values, int[] status, long[] timestamp);
17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1745