SensorManager.java revision 0871ee0c6f43a7201ce49a66211c1c850eabeb6b
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;
27ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopianimport android.util.SparseBooleanArray;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IRotationWatcher;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowManager;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Surface;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collections;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
3843c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * <p>
3974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * SensorManager lets you access the device's {@link android.hardware.Sensor
4074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * sensors}. Get an instance of this class by calling
4174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * {@link android.content.Context#getSystemService(java.lang.String)
4274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * Context.getSystemService()} with the argument
4374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * {@link android.content.Context#SENSOR_SERVICE}.
4443c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * </p>
4543c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * <p>
4643c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * Always make sure to disable sensors you don't need, especially when your
4743c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * activity is paused. Failing to do so can drain the battery in just a few
4843c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * hours. Note that the system will <i>not</i> disable sensors automatically when
4943c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * the screen turns off.
5043c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * </p>
510f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
520f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * <pre class="prettyprint">
530f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * public class SensorActivity extends Activity, implements SensorEventListener {
540f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     private final SensorManager mSensorManager;
550f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     private final Sensor mAccelerometer;
560f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
570f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     public SensorActivity() {
580f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *         mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
590f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *         mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
6043c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     }
6143c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *
6243c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     protected void onResume() {
6343c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *         super.onResume();
640f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *         mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
650f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     }
660f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
6743c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     protected void onPause() {
6843c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *         super.onPause();
6943c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *         mSensorManager.unregisterListener(this);
7043c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     }
7143c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *
720f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     public void onAccuracyChanged(Sensor sensor, int accuracy) {
730f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     }
740f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
7543c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     public void onSensorChanged(SensorEvent event) {
760f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     }
770f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * }
780f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * </pre>
790f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
800f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * @see SensorEventListener
810f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * @see SensorEvent
820f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * @see Sensor
830f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
85287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopianpublic class SensorManager
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "SensorManager";
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final float[] mTempMatrix = new float[16];
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* NOTE: sensor IDs must be a power of 2 */
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an orientation 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_ORIENTATION = 1 << 0;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an accelerometer. 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_ACCELEROMETER = 1 << 1;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a temperature 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_TEMPERATURE = 1 << 2;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a magnetic 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_MAGNETIC_FIELD = 1 << 3;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an ambient light sensor 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_LIGHT = 1 << 4;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a proximity 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_PROXIMITY = 1 << 5;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a Tricorder See
14874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1490f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_TRICORDER = 1 << 6;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an orientation sensor. See
15774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1580f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
16574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant that includes all sensors
1660f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1674a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1684a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ALL = 0x7F;
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
17374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Smallest sensor ID
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 SENSOR_MIN = SENSOR_ORIENTATION;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
18174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Largest sensor ID
1820f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1834a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1844a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1);
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
19074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the X 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_X = 0;
19774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
19874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
19974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the Y value 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 DATA_Y = 1;
20674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
20774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
20874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the Z 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 DATA_Z = 2;
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
21774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Offset to the untransformed values 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_INDEX = 3;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
22674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed X 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_X = 3;
23374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
23474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
23574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed Y value in the array returned by
2364a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2370f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2384a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2394a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_Y = 4;
24274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
24374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
24474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed Z value in the array returned by
2454a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2460f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2474a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2484a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_Z = 5;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Standard gravity (g) on Earth. This value is equivalent to 1G */
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float STANDARD_GRAVITY = 9.80665f;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Sun's gravity in SI units (m/s^2) */
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_SUN             = 275.0f;
25774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Mercury's gravity in SI units (m/s^2) */
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MERCURY         = 3.70f;
25974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Venus' gravity in SI units (m/s^2) */
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_VENUS           = 8.87f;
26174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Earth's gravity in SI units (m/s^2) */
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_EARTH           = 9.80665f;
26374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** The Moon's gravity in SI units (m/s^2) */
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MOON            = 1.6f;
26574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Mars' gravity in SI units (m/s^2) */
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MARS            = 3.71f;
26774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Jupiter's gravity in SI units (m/s^2) */
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_JUPITER         = 23.12f;
26974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Saturn's gravity in SI units (m/s^2) */
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_SATURN          = 8.96f;
27174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Uranus' gravity in SI units (m/s^2) */
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_URANUS          = 8.69f;
27374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Neptune's gravity in SI units (m/s^2) */
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_NEPTUNE         = 11.0f;
27574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Pluto's gravity in SI units (m/s^2) */
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_PLUTO           = 0.6f;
27774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_DEATH_STAR_I    = 0.000000353036145f;
27974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Gravity on the island */
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_THE_ISLAND      = 4.815162342f;
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Maximum magnetic field on Earth's surface */
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f;
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Minimum magnetic field on Earth's surface */
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2880f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian
28904d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian    /** Standard atmosphere, or average sea-level pressure in hPa (millibar) */
29004d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian    public static final float PRESSURE_STANDARD_ATMOSPHERE = 1013.25f;
29104d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian
29204d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian
29374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Maximum luminance of sunlight in lux */
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
29574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance of sunlight in lux */
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNLIGHT     = 110000.0f;
29774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance in shade in lux */
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SHADE        = 20000.0f;
29974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance under an overcast sky in lux */
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_OVERCAST     = 10000.0f;
30174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at sunrise in lux */
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNRISE      = 400.0f;
30374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance under a cloudy sky in lux */
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_CLOUDY       = 100.0f;
30574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at night with full moon in lux */
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_FULLMOON     = 0.25f;
30774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at night with no moon in lux*/
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_NO_MOON      = 0.001f;
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3100f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** get sensor data as fast as possible */
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_FASTEST = 0;
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate suitable for games */
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_GAME = 1;
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate suitable for the user interface  */
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_UI = 2;
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate (default) suitable for screen orientation changes */
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_NORMAL = 3;
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
32174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
32274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The values returned by this sensor cannot be trusted, calibration is
32374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * needed or the environment doesn't allow readings
32474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_UNRELIABLE = 0;
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
32774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
32874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This sensor is reporting data with low accuracy, calibration with the
32974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * environment is needed
33074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
33374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
33474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This sensor is reporting data with an average level of accuracy,
33574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * calibration with the environment may improve the readings
33674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** This sensor is reporting data with maximum accuracy */
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_X = 1;
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_Y = 2;
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_Z = 3;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_X = AXIS_X | 0x80;
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_Y = AXIS_Y | 0x80;
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_Z = AXIS_Z | 0x80;
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Looper mMainLooper;
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("deprecation")
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<SensorListener, LegacyListener> mLegacyListenersMap =
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<SensorListener, LegacyListener>();
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int SENSOR_DISABLE = -1;
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean sSensorModuleInitialized = false;
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static SparseArray<List<Sensor>> sSensorListByType = new SparseArray<List<Sensor>>();
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static IWindowManager sWindowManager;
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int sRotation = Surface.ROTATION_0;
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* The thread and the sensor list are global to the process
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * but the actual thread is spawned on demand */
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static SensorThread sSensorThread;
3731bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    private static int sQueue;
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Used within this module from outside SensorManager, don't make private
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final ArrayList<ListenerDelegate> sListeners =
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new ArrayList<ListenerDelegate>();
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static private class SensorThread {
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Thread mThread;
385b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian        boolean mSensorsReady;
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SensorThread() {
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected void finalize() {
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // must be called with sListeners lock
3951bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        boolean startLocked() {
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mThread == null) {
3981bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    mSensorsReady = false;
3991bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    SensorThreadRunnable runnable = new SensorThreadRunnable();
4001bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    Thread thread = new Thread(runnable, SensorThread.class.getName());
4011bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    thread.start();
4021bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    synchronized (runnable) {
4031bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                        while (mSensorsReady == false) {
4041bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                            runnable.wait();
405b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                        }
406b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                    }
4071bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    mThread = thread;
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
409b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian            } catch (InterruptedException e) {
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
411b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian            return mThread == null ? false : true;
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private class SensorThreadRunnable implements Runnable {
4151bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            SensorThreadRunnable() {
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
417270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood
418270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood            private boolean open() {
419b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                // NOTE: this cannot synchronize on sListeners, since
420b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                // it's held in the main thread at least until we
421b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                // return from here.
4221bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                sQueue = sensors_create_queue();
423270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                return true;
424270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood            }
425270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public void run() {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //Log.d(TAG, "entering main sensor thread");
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float[] values = new float[3];
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int[] status = new int[1];
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final long timestamp[] = new long[1];
431e417158c06c81c8c4dc6794c5421b711e671c7e3Mathias Agopian                Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
433270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                if (!open()) {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return;
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
437b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                synchronized (this) {
438b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                    // we've open the driver, we're ready to open the sensors
439b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                    mSensorsReady = true;
440b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                    this.notify();
441b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                }
442b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while (true) {
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // wait for an event
4451bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    final int sensor = sensors_data_poll(sQueue, values, status, timestamp);
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    int accuracy = status[0];
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (sListeners) {
4496dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                        if (sensor == -1 || sListeners.isEmpty()) {
4504d3cb63b9b9177b79c575ca1b21040cc42ee7879Mathias Agopian                            // we lost the connection to the event stream. this happens
4514d3cb63b9b9177b79c575ca1b21040cc42ee7879Mathias Agopian                            // when the last listener is removed or if there is an error
4524d3cb63b9b9177b79c575ca1b21040cc42ee7879Mathias Agopian                            if (sensor == -1 && !sListeners.isEmpty()) {
4534d3cb63b9b9177b79c575ca1b21040cc42ee7879Mathias Agopian                                // log a warning in case of abnormal termination
4544d3cb63b9b9177b79c575ca1b21040cc42ee7879Mathias Agopian                                Log.e(TAG, "_sensors_data_poll() failed, we bail out: sensors=" + sensor);
4556dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                            }
4566dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                            // we have no more listeners or polling failed, terminate the thread
4571bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                            sensors_destroy_queue(sQueue);
4581bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                            sQueue = 0;
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mThread = null;
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            break;
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        final Sensor sensorObject = sHandleToSensor.get(sensor);
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (sensorObject != null) {
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // report the sensor event to all listeners that
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // care about it.
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            final int size = sListeners.size();
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            for (int i=0 ; i<size ; i++) {
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                ListenerDelegate listener = sListeners.get(i);
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (listener.hasSensor(sensorObject)) {
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    // this is asynchronous (okay to call
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    // with sListeners lock held).
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    listener.onSensorChangedLocked(sensorObject,
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            values, timestamp, accuracy);
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //Log.d(TAG, "exiting main sensor thread");
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4861bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    private class ListenerDelegate {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final SensorEventListener mSensorEventListener;
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final Handler mHandler;
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private SensorEvent mValuesPool;
491ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian        public SparseBooleanArray mSensors = new SparseBooleanArray();
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensorEventListener = listener;
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // currently we create one Handler instance per listener, but we could
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // have one per looper (we'd need to pass the ListenerDelegate
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // instance to handleMessage and keep track of them separately).
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler = new Handler(looper) {
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                @Override
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                public void handleMessage(Message msg) {
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SensorEvent t = (SensorEvent)msg.obj;
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.accuracy >= 0) {
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy);
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mSensorEventListener.onSensorChanged(t);
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    returnToPool(t);
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            };
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            addSensor(sensor);
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected SensorEvent createSensorEvent() {
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // maximal size for all legacy events is 3
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new SensorEvent(3);
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected SensorEvent getFromPool() {
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorEvent t = null;
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // remove the array from the pool
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                t = mValuesPool;
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mValuesPool = null;
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (t == null) {
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // the pool was empty, we need a new one
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                t = createSensorEvent();
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return t;
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected void returnToPool(SensorEvent t) {
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // put back the array into the pool
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mValuesPool == null) {
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mValuesPool = t;
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Object getListener() {
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSensorEventListener;
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
545ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian        void addSensor(Sensor sensor) {
546ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian            mSensors.put(sensor.getHandle(), true);
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensorList.add(sensor);
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int removeSensor(Sensor sensor) {
550ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian            mSensors.delete(sensor.getHandle());
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensorList.remove(sensor);
552ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian            return mSensors.size();
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean hasSensor(Sensor sensor) {
555ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian            return mSensors.get(sensor.getHandle());
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> getSensors() {
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSensorList;
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void onSensorChangedLocked(Sensor sensor, float[] values, long[] timestamp, int accuracy) {
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorEvent t = getFromPool();
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float[] v = t.values;
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[0] = values[0];
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[1] = values[1];
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[2] = values[2];
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.timestamp = timestamp[0];
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.accuracy = accuracy;
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.sensor = sensor;
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Message msg = Message.obtain();
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            msg.what = 0;
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            msg.obj = t;
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler.sendMessage(msg);
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SensorManager(Looper mainLooper) {
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMainLooper = mainLooper;
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(sListeners) {
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!sSensorModuleInitialized) {
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sSensorModuleInitialized = true;
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                nativeClassInit();
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sWindowManager = IWindowManager.Stub.asInterface(
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ServiceManager.getService("window"));
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (sWindowManager != null) {
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // if it's null we're running in the system process
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // which won't get the rotated values
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
596287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                        sRotation = sWindowManager.watchRotation(
59704d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian                                new IRotationWatcher.Stub() {
59804d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian                                    public void onRotationChanged(int rotation) {
59904d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian                                        SensorManager.this.onRotationChanged(rotation);
60004d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian                                    }
601287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                                }
602287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                        );
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // initialize the sensor list
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sensors_module_init();
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final ArrayList<Sensor> fullList = sFullSensorsList;
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int i = 0;
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Sensor sensor = new Sensor();
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i = sensors_module_get_next_sensor(sensor, i);
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (i>=0) {
616f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato                        //Log.d(TAG, "found sensor: " + sensor.getName() +
617f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato                        //        ", handle=" + sensor.getHandle());
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sensor.setLegacyType(getLegacySensorType(sensor.getType()));
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fullList.add(sensor);
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sHandleToSensor.append(sensor.getHandle(), sensor);
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } while (i>0);
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sSensorThread = new SensorThread();
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getLegacySensorType(int type) {
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (type) {
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_ACCELEROMETER:
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_ACCELEROMETER;
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_MAGNETIC_FIELD:
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_MAGNETIC_FIELD;
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_ORIENTATION:
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_ORIENTATION_RAW;
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_TEMPERATURE:
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_TEMPERATURE;
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
64374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
64474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return available sensors.
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
64674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#getSensorList(int)} instead
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getSensors() {
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int result = 0;
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ArrayList<Sensor> fullList = sFullSensorsList;
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (Sensor i : fullList) {
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (i.getType()) {
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_ACCELEROMETER:
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_ACCELEROMETER;
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_MAGNETIC_FIELD:
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_MAGNETIC_FIELD;
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_ORIENTATION:
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_ORIENTATION |
66204d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian                    SensorManager.SENSOR_ORIENTATION_RAW;
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
67074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Use this method to get the list of available sensors of a certain type.
67174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Make multiple calls to get sensors of different types or use
67274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the
67374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * sensors.
6740f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
67574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param type
67674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        of sensors requested
6770f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a list of sensors matching the asked type.
6790f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
6800f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getDefaultSensor(int)
6810f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see Sensor
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<Sensor> getSensorList(int type) {
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // cache the returned lists the first time
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> list;
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ArrayList<Sensor> fullList = sFullSensorsList;
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(fullList) {
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            list = sSensorListByType.get(type);
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (list == null) {
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (type == Sensor.TYPE_ALL) {
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    list = fullList;
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    list = new ArrayList<Sensor>();
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (Sensor i : fullList) {
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (i.getType() == type)
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            list.add(i);
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                list = Collections.unmodifiableList(list);
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sSensorListByType.append(type, list);
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return list;
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
70774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Use this method to get the default sensor for a given type. Note that the
70874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * returned sensor could be a composite sensor, and its data could be
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * averaged or filtered. If you need to access the raw sensors use
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link SensorManager#getSensorList(int) getSensorList}.
7110f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
71274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param type
71374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        of sensors requested
7140f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the default sensors matching the asked type.
7160f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
7170f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getSensorList(int)
7180f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see Sensor
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Sensor getDefaultSensor(int type) {
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: need to be smarter, for now, just return the 1st sensor
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> l = getSensorList(type);
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return l.isEmpty() ? null : l.get(0);
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registers a listener 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     * @return <code>true</code> if the sensor is supported and successfully
74074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorListener listener, int sensors) {
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registers a SensorListener for given sensors.
7490f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
75174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
75274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
7530f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
75474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
75574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        sensor listener object
7560f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
75774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensors
75874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a bit masks of the sensors to register to
7590f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
76074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param rate
76174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        rate of events. This is only a hint to the system. events may be
76274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
76374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
76474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
76574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
7660f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
76774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> if the sensor is supported and successfully
76874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorListener listener, int sensors, int rate) {
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        result = registerLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("deprecation")
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean registerLegacyListener(int legacyType, int type,
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorListener listener, int sensors, int rate)
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result = false;
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Are we activating this legacy sensor?
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((sensors & legacyType) != 0) {
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // if so, find a suitable Sensor
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Sensor sensor = getDefaultSensor(type);
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sensor != null) {
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If we don't already have one, create a LegacyListener
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // to wrap this listener and process the events as
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // they are expected by legacy apps.
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                LegacyListener legacyListener = null;
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                synchronized (mLegacyListenersMap) {
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    legacyListener = mLegacyListenersMap.get(listener);
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (legacyListener == null) {
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // we didn't find a LegacyListener for this client,
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // create one, and put it in our list.
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        legacyListener = new LegacyListener(listener);
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mLegacyListenersMap.put(listener, legacyListener);
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // register this legacy sensor with this legacy listener
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                legacyListener.registerSensor(legacyType);
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // and finally, register the legacy listener with the new apis
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                result = registerListener(legacyListener, sensor, rate);
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for the sensors with which it is registered.
8260f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
82874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#unregisterListener(SensorEventListener, Sensor)}
82974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
8300f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
83174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
83274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
8330f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
83474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensors
83574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a bit masks of the sensors to unregister from
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorListener listener, int sensors) {
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("deprecation")
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void unregisterLegacyListener(int legacyType, int type,
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorListener listener, int sensors)
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // do we know about this listener?
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LegacyListener legacyListener = null;
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mLegacyListenersMap) {
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            legacyListener = mLegacyListenersMap.get(listener);
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (legacyListener != null) {
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Are we deactivating this legacy sensor?
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((sensors & legacyType) != 0) {
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // if so, find the corresponding Sensor
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Sensor sensor = getDefaultSensor(type);
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (sensor != null) {
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // unregister this legacy sensor and if we don't
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // need the corresponding Sensor, unregister it too
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (legacyListener.unregisterSensor(legacyType)) {
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // corresponding sensor not needed, unregister
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        unregisterListener(legacyListener, sensor);
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // finally check if we still need the legacyListener
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // in our mapping, if not, get rid of it too.
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        synchronized(sListeners) {
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            boolean found = false;
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            for (ListenerDelegate i : sListeners) {
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (i.getListener() == legacyListener) {
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    found = true;
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    break;
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (!found) {
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                synchronized (mLegacyListenersMap) {
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    mLegacyListenersMap.remove(listener);
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for all sensors.
8980f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
90074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#unregisterListener(SensorEventListener)}
90174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
9020f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
90374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
90474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorListener listener) {
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for the sensors with which it is registered.
9130f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
91474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
91574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorEventListener object
9160f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
91774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
91874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the sensor to unregister from
9190f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9200f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener)
9210f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int)
9220f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorEventListener listener, Sensor sensor) {
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterListener((Object)listener, sensor);
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for all sensors.
9300f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
93174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
93274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
9330f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9340f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener, Sensor)
9350f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int)
9360f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorEventListener listener) {
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterListener((Object)listener);
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
94374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Registers a {@link android.hardware.SensorEventListener
94474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * SensorEventListener} for the given sensor.
9450f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
94674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
94774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        A {@link android.hardware.SensorEventListener SensorEventListener}
94874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        object.
9490f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
95074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
95174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.hardware.Sensor Sensor} to register to.
9520f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
95374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param rate
95474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The rate {@link android.hardware.SensorEvent sensor events} are
95574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered at. This is only a hint to the system. Events may be
95674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
95774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
95874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
959050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}
960050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian     *        or, the desired delay between events in microsecond.
9610f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
96274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> if the sensor is supported and successfully
96374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled.
9640f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9650f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int, Handler)
9660f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener)
9670f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener, Sensor)
9680f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return registerListener(listener, sensor, rate, null);
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
974ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian    private boolean enableSensorLocked(Sensor sensor, int delay) {
975ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian        boolean result = false;
976ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian        for (ListenerDelegate i : sListeners) {
977ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian            if (i.hasSensor(sensor)) {
978ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                String name = sensor.getName();
979ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                int handle = sensor.getHandle();
980ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                result = sensors_enable_sensor(sQueue, name, handle, delay);
981ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                break;
982ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian            }
983ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian        }
984ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian        return result;
985ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian    }
986ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian
987ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian    private boolean disableSensorLocked(Sensor sensor) {
988ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian        for (ListenerDelegate i : sListeners) {
989ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian            if (i.hasSensor(sensor)) {
990ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                // not an error, it's just that this sensor is still in use
991ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                return true;
992ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian            }
993ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian        }
994ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian        String name = sensor.getName();
995ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian        int handle = sensor.getHandle();
996ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian        return sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
997ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian    }
998ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
100074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Registers a {@link android.hardware.SensorEventListener
100174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * SensorEventListener} for the given sensor.
10020f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
100374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
100474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        A {@link android.hardware.SensorEventListener SensorEventListener}
100574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        object.
10060f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
100774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
100874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.hardware.Sensor Sensor} to register to.
10090f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
101074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param rate
101174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The rate {@link android.hardware.SensorEvent sensor events} are
101274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered at. This is only a hint to the system. Events may be
101374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
101474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
101574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
101674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
1017050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian     *        or, the desired delay between events in microsecond.
10180f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
101974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param handler
102074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.os.Handler Handler} the
102174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent sensor events} will be
102274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered to.
10230f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the sensor is supported and successfully enabled.
10250f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
10260f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int)
10270f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener)
10280f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener, Sensor)
10290f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Handler handler) {
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null || sensor == null) {
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1036ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian        boolean result = true;
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int delay = -1;
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (rate) {
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_FASTEST:
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delay = 0;
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_GAME:
1043050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian                delay = 20000;
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_UI:
1046050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian                delay = 60000;
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_NORMAL:
1049050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian                delay = 200000;
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
1052050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian                delay = rate;
1053050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian                break;
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10561bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        synchronized (sListeners) {
1057ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian            // look for this listener in our list
10581bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            ListenerDelegate l = null;
10591bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            for (ListenerDelegate i : sListeners) {
10601bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                if (i.getListener() == listener) {
10611bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    l = i;
10621bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    break;
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10641bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            }
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1066ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian            // if we don't find it, add it to the list
10671bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            if (l == null) {
10681bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                l = new ListenerDelegate(listener, sensor, handler);
10691bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                sListeners.add(l);
1070ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                // if the list is not empty, start our main thread
10711bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                if (!sListeners.isEmpty()) {
1072ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                    if (sSensorThread.startLocked()) {
1073ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                        if (!enableSensorLocked(sensor, delay)) {
1074ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                            // oops. there was an error
10751bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                            sListeners.remove(l);
1076ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                            result = false;
10771bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                        }
1078ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                    } else {
1079ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                        // there was an error, remove the listener
1080ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                        sListeners.remove(l);
1081ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                        result = false;
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1083ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                } else {
1084ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                    // weird, we couldn't add the listener
1085ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                    result = false;
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10871bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            } else {
1088ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                l.addSensor(sensor);
1089ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                if (!enableSensorLocked(sensor, delay)) {
1090ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                    // oops. there was an error
1091ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                    l.removeSensor(sensor);
1092ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                    result = false;
10931bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                }
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1096ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void unregisterListener(Object listener, Sensor sensor) {
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null || sensor == null) {
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11044d3cb63b9b9177b79c575ca1b21040cc42ee7879Mathias Agopian
11051bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        synchronized (sListeners) {
11061bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            final int size = sListeners.size();
11071bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            for (int i=0 ; i<size ; i++) {
11081bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                ListenerDelegate l = sListeners.get(i);
11091bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                if (l.getListener() == listener) {
11101bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    if (l.removeSensor(sensor) == 0) {
1111ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                        // if we have no more sensors enabled on this listener,
1112ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                        // take it off the list.
11131bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                        sListeners.remove(i);
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11151bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    break;
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1118ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian            disableSensorLocked(sensor);
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void unregisterListener(Object listener) {
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11264d3cb63b9b9177b79c575ca1b21040cc42ee7879Mathias Agopian
11271bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        synchronized (sListeners) {
11281bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            final int size = sListeners.size();
11291bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            for (int i=0 ; i<size ; i++) {
11301bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                ListenerDelegate l = sListeners.get(i);
11311bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                if (l.getListener() == listener) {
1132ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                    sListeners.remove(i);
11331bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    // disable all sensors for this listener
11341bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    for (Sensor sensor : l.getSensors()) {
1135ec33b82c42f3dd996a72b80359c87524b51ffb2aMathias Agopian                        disableSensorLocked(sensor);
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11371bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    break;
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
114474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
114574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Computes the inclination matrix <b>I</b> as well as the rotation matrix
114674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>R</b> transforming a vector from the device coordinate system to the
114774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * world's coordinate system which is defined as a direct orthonormal basis,
114874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * where:
114974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
11500f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
115174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the ground at the device's current location and roughly points East).</li>
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Y is tangential to the ground at the device's current location and
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * points towards the magnetic North Pole.</li>
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Z points towards the sky and is perpendicular to the ground.</li>
115774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
11580f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
11590f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * <p>
11600f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * <center><img src="../../../images/axis_globe.png"
1161f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * alt="World coordinate-system diagram." border="0" /></center>
11620f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * </p>
11630f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
116674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
116774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * By definition:
116874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
116974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * [0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity)
117074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
117174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * [0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b> (m = magnitude of
117274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * geomagnetic field)
117374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
117474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>R</b> is the identity matrix when the device is aligned with the
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * world's coordinate system, that is, when the device's X axis points
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * toward East, the Y axis points to the North Pole and the device is facing
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the sky.
11780f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
117974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
118074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>I</b> is a rotation matrix transforming the geomagnetic vector into
118174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * the same coordinate space as gravity (the world's coordinate space).
118274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>I</b> is a simple rotation around the X axis. The inclination angle in
118374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * radians can be computed with {@link #getInclination}.
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
11850f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
118674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
118774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Each matrix is returned either as a 3x3 or 4x4 row-major matrix depending
118874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * on the length of the passed array:
118974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
119074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>If the array length is 16:</u>
11910f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]   M[ 3]  \
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 4]   M[ 5]   M[ 6]   M[ 7]  |
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 8]   M[ 9]   M[10]   M[11]  |
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \  M[12]   M[13]   M[14]   M[15]  /
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
11980f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
119974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This matrix is ready to be used by OpenGL ES's
120074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int)
120174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * glLoadMatrixf(float[], int)}.
120274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
120374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Note that because OpenGL matrices are column-major matrices you must
120474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * transpose the matrix before using it. However, since the matrix is a
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rotation matrix, its transpose is also its inverse, conveniently, it is
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * often the inverse of the rotation that is needed for rendering; it can
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * therefore be used with OpenGL ES directly.
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Also note that the returned matrices always have this form:
12100f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]   0  \
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 4]   M[ 5]   M[ 6]   0  |
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 8]   M[ 9]   M[10]   0  |
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \      0       0       0   1  /
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
12170f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
121874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
121974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>If the array length is 9:</u>
12200f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]  \
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 3]   M[ 4]   M[ 5]  |
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \  M[ 6]   M[ 7]   M[ 8]  /
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
12260f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
122874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
122974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The inverse of each matrix can be computed easily by taking its
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * transpose.
12310f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
123274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
123374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The matrices returned by this function are meaningful only when the
123474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * device is not free-falling and it is not close to the magnetic north. If
123574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * the device is accelerating, or placed into a strong magnetic field, the
123674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * returned matrices may be inaccurate.
12370f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
123874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param R
123974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 9 floats holding the rotation matrix <b>R</b> when
124074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        this function returns. R can be null.
124174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
12420f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
124374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param I
124474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 9 floats holding the rotation matrix <b>I</b> when
124574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        this function returns. I can be null.
124674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
12470f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
124874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param gravity
124974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 3 floats containing the gravity vector expressed in
125074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the device's coordinate. You can simply use the
125174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent#values values} returned by a
125274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent SensorEvent} of a
125374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor Sensor} of type
125474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor#TYPE_ACCELEROMETER
125574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        TYPE_ACCELEROMETER}.
125674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
12570f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
125874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param geomagnetic
125974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 3 floats containing the geomagnetic vector
126074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        expressed in the device's coordinate. You can simply use the
126174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent#values values} returned by a
126274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent SensorEvent} of a
126374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor Sensor} of type
126474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD
126574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        TYPE_MAGNETIC_FIELD}.
12660f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
126774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> on success, <code>false</code> on failure (for
126874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         instance, if the device is in free fall). On failure the output
126974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         matrices are not modified.
12700f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
12710f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getInclination(float[])
12720f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getOrientation(float[], float[])
12730f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #remapCoordinateSystem(float[], int, int, float[])
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean getRotationMatrix(float[] R, float[] I,
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] gravity, float[] geomagnetic) {
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: move this to native code for efficiency
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Ax = gravity[0];
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Ay = gravity[1];
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Az = gravity[2];
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ex = geomagnetic[0];
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ey = geomagnetic[1];
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ez = geomagnetic[2];
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hx = Ey*Az - Ez*Ay;
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hy = Ez*Ax - Ex*Az;
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hz = Ex*Ay - Ey*Ax;
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (normH < 0.1f) {
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // device is close to free fall (or in space?), or close to
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // magnetic north pole. Typical values are  > 100.
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float invH = 1.0f / normH;
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hx *= invH;
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hy *= invH;
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hz *= invH;
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Ax *= invA;
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Ay *= invA;
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Az *= invA;
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Mx = Ay*Hz - Az*Hy;
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float My = Az*Hx - Ax*Hz;
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Mz = Ax*Hy - Ay*Hx;
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (R != null) {
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (R.length == 9) {
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[0] = Hx;     R[1] = Hy;     R[2] = Hz;
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[3] = Mx;     R[4] = My;     R[5] = Mz;
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[6] = Ax;     R[7] = Ay;     R[8] = Az;
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (R.length == 16) {
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[0]  = Hx;    R[1]  = Hy;    R[2]  = Hz;   R[3]  = 0;
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[4]  = Mx;    R[5]  = My;    R[6]  = Mz;   R[7]  = 0;
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[8]  = Ax;    R[9]  = Ay;    R[10] = Az;   R[11] = 0;
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[12] = 0;     R[13] = 0;     R[14] = 0;    R[15] = 1;
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (I != null) {
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // compute the inclination matrix by projecting the geomagnetic
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // vector onto the Z (gravity) and X (horizontal component
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // of geomagnetic vector) axes.
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (I.length == 9) {
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[0] = 1;     I[1] = 0;     I[2] = 0;
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[3] = 0;     I[4] = c;     I[5] = s;
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[6] = 0;     I[7] =-s;     I[8] = c;
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (I.length == 16) {
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[0] = 1;     I[1] = 0;     I[2] = 0;
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[4] = 0;     I[5] = c;     I[6] = s;
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[8] = 0;     I[9] =-s;     I[10]= c;
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[15] = 1;
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes the geomagnetic inclination angle in radians from the
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}.
13420f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
134374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param I
134474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        inclination matrix see {@link #getRotationMatrix}.
13450f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The geomagnetic inclination angle in radians.
13470f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
13480f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getRotationMatrix(float[], float[], float[], float[])
13490f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getOrientation(float[], float[])
13500f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see GeomagneticField
13510f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static float getInclination(float[] I) {
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (I.length == 9) {
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (float)Math.atan2(I[5], I[4]);
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
13570f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian            return (float)Math.atan2(I[6], I[5]);
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
136274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
136374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Rotates the supplied rotation matrix so it is expressed in a different
136474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * coordinate system. This is typically used when an application needs to
136574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * compute the three orientation angles of the device (see
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getOrientation}) in a different coordinate system.
136774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
13680f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
136974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
137074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * When the rotation matrix is used for drawing (for instance with OpenGL
137174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * ES), it usually <b>doesn't need</b> to be transformed by this function,
137274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * unless the screen is physically rotated, in which case you can use
137374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.view.Display#getRotation() Display.getRotation()} to
137474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * retrieve the current rotation of the screen. Note that because the user
137574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * is generally free to rotate their screen, you often should consider the
137674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * rotation in deciding the parameters to use here.
137774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
13780f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
137974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
138074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>Examples:</u>
138174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
13820f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
138374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
138474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <li>Using the camera (Y axis along the camera's axis) for an augmented
138574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * reality application where the rotation angles are needed:</li>
13860f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
138774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
138874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
138974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code>
139074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
139174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
13920f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
13935cb70b54156fb305d579a1cc167424c8705bfdf7Dianne Hackborn     * <li>Using the device as a mechanical compass when rotation is
139474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:</li>
13950f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
139674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
139774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
139874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code>
139974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
140074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
14010f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
140274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Beware of the above example. This call is needed only to account for a
140374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * rotation from its natural orientation when calculating the rotation
140474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * angles (see {@link #getOrientation}). If the rotation matrix is also used
140574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * for rendering, it may not need to be transformed, for instance if your
140674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.app.Activity Activity} is running in landscape mode.
140774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
14080f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
140974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
141074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Since the resulting coordinate system is orthonormal, only two axes need
141174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * to be specified.
14120f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
141374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param inR
141474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the rotation matrix to be transformed. Usually it is the matrix
141574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        returned by {@link #getRotationMatrix}.
14160f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
141774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param X
141874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        defines on which world axis and direction the X axis of the device
141974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is mapped.
14200f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
142174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param Y
142274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        defines on which world axis and direction the Y axis of the device
142374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is mapped.
14240f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
142574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param outR
142674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the transformed rotation matrix. inR and outR can be the same
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        array, but it is not recommended for performance reason.
14280f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
142974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> on success. <code>false</code> if the input
143074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         parameters are incorrect, for instance if X and Y define the same
143174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         axis. Or if inR and outR don't have the same length.
14320f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
14330f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getRotationMatrix(float[], float[], float[], float[])
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean remapCoordinateSystem(float[] inR, int X, int Y,
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] outR)
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (inR == outR) {
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float[] temp = mTempMatrix;
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(temp) {
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // we don't expect to have a lot of contention
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final int size = outR.length;
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (int i=0 ; i<size ; i++)
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        outR[i] = temp[i];
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return true;
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return remapCoordinateSystemImpl(inR, X, Y, outR);
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y,
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] outR)
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * X and Y define a rotation matrix 'r':
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *                              r[0] ^ r[1]
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * where the 3rd line is the vector product of the first 2 lines
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int length = outR.length;
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (inR.length != length)
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // invalid parameter
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((X & 0x7C)!=0 || (Y & 0x7C)!=0)
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // invalid parameter
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (((X & 0x3)==0) || ((Y & 0x3)==0))
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // no axis specified
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((X & 0x3) == (Y & 0x3))
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // same axis specified
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // this can be calculated by exclusive-or'ing X and Y; except for
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the sign inversion (+/-) which is calculated below.
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int Z = X ^ Y;
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // extract the axis (remove the sign), offset in the range 0 to 2.
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int x = (X & 0x3)-1;
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int y = (Y & 0x3)-1;
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int z = (Z & 0x3)-1;
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // compute the sign of Z (whether it needs to be inverted)
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int axis_y = (z+1)%3;
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int axis_z = (z+2)%3;
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (((x^axis_y)|(y^axis_z)) != 0)
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Z ^= 0x80;
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sx = (X>=0x80);
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sy = (Y>=0x80);
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sz = (Z>=0x80);
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Perform R * r, in avoiding actual muls and adds.
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int rowLength = ((length==16)?4:3);
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int j=0 ; j<3 ; j++) {
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int offset = j*rowLength;
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0 ; i<3 ; i++) {
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (x==i)   outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0];
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (y==i)   outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1];
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (z==i)   outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2];
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (length == 16) {
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            outR[15] = 1;
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes the device's orientation based on the rotation matrix.
151774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
151874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * When it returns, the array values is filled with the result:
151974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[0]: <i>azimuth</i>, rotation around the Z axis.</li>
15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[1]: <i>pitch</i>, rotation around the X axis.</li>
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li>
152374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
1524f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <p>The reference coordinate-system used is different from the world
1525f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * coordinate-system defined for the rotation matrix:</p>
1526f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <ul>
1527f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
1528f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * the ground at the device's current location and roughly points West).</li>
1529f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <li>Y is tangential to the ground at the device's current location and
1530f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * points towards the magnetic North Pole.</li>
1531f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <li>Z points towards the center of the Earth and is perpendicular to the ground.</li>
1532f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * </ul>
1533f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     *
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
15350871ee0c6f43a7201ce49a66211c1c850eabeb6bDirk Dougherty     * <center><img src="../../../images/axis_globe_inverted.png"
1536f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * alt="Inverted world coordinate-system diagram." border="0" /></center>
15370f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * </p>
15380f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * <p>
1539210fc914db37b3cf77ebb3bf75b0b509a1ecb07cMathias Agopian     * All three angles above are in <b>radians</b> and <b>positive</b> in the
1540210fc914db37b3cf77ebb3bf75b0b509a1ecb07cMathias Agopian     * <b>counter-clockwise</b> direction.
154174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
154274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param R
154374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        rotation matrix see {@link #getRotationMatrix}.
15440f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
154574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param values
154674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        an array of 3 floats to hold the result.
15470f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The array values passed as argument.
15490f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
15500f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getRotationMatrix(float[], float[], float[], float[])
15510f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see GeomagneticField
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
155304d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian    public static float[] getOrientation(float[] R, float values[]) {
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * 4x4 (length=16) case:
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   /  R[ 0]   R[ 1]   R[ 2]   0  \
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 4]   R[ 5]   R[ 6]   0  |
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 8]   R[ 9]   R[10]   0  |
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   \      0       0       0   1  /
15600f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian         *
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * 3x3 (length=9) case:
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   /  R[ 0]   R[ 1]   R[ 2]  \
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 3]   R[ 4]   R[ 5]  |
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   \  R[ 6]   R[ 7]   R[ 8]  /
15650f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian         *
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (R.length == 9) {
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = (float)Math.atan2(R[1], R[4]);
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = (float)Math.asin(-R[7]);
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = (float)Math.atan2(-R[6], R[8]);
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = (float)Math.atan2(R[1], R[5]);
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = (float)Math.asin(-R[9]);
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = (float)Math.atan2(-R[8], R[10]);
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return values;
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
158004d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * Computes the Altitude in meters from the atmospheric pressure and the
158104d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * pressure at sea level.
158204d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * <p>
158304d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * Typically the atmospheric pressure is read from a
158404d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * {@link Sensor#TYPE_PRESSURE} sensor. The pressure at sea level must be
158504d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * known, usually it can be retrieved from airport databases in the
1586a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * vicinity. If unknown, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE}
1587a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * as an approximation, but absolute altitudes won't be accurate.
1588a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * </p>
1589a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * <p>
1590a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * To calculate altitude differences, you must calculate the difference
1591a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * between the altitudes at both points. If you don't know the altitude
1592a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * as sea level, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE} instead,
1593a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * which will give good results considering the range of pressure typically
1594a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * involved.
1595a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * </p>
1596a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * <p>
1597a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * <code><ul>
1598a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     *  float altitude_difference =
1599a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     *      getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point2)
1600a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     *      - getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point1);
1601a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * </ul></code>
160204d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * </p>
160304d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     *
160404d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * @param p0 pressure at sea level
160504d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * @param p atmospheric pressure
160604d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * @return Altitude in meters
160704d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     */
160804d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian   public static float getAltitude(float p0, float p) {
160904d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian        final float coef = 1.0f / 5.255f;
161004d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian        return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef));
161104d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian    }
161204d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian
161304d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian
161404d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian   /**
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onRotationChanged(int rotation) {
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(sListeners) {
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sRotation  = rotation;
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static int getRotation() {
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(sListeners) {
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return sRotation;
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class LegacyListener implements SensorEventListener {
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mValues[] = new float[6];
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private SensorListener mTarget;
16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mSensors;
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final LmsFilter mYawfilter = new LmsFilter();
16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LegacyListener(SensorListener target) {
16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTarget = target;
16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors = 0;
16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void registerSensor(int legacyType) {
16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors |= legacyType;
16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean unregisterSensor(int legacyType) {
16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors &= ~legacyType;
16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mask = SENSOR_ORIENTATION|SENSOR_ORIENTATION_RAW;
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (((legacyType&mask)!=0) && ((mSensors&mask)!=0)) {
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onAccuracyChanged(Sensor sensor, int accuracy) {
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTarget.onAccuracyChanged(sensor.getLegacyType(), accuracy);
16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (AbstractMethodError e) {
16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // old app that doesn't implement this method
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // just ignore it.
16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onSensorChanged(SensorEvent event) {
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float v[] = mValues;
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[0] = event.values[0];
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[1] = event.values[1];
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[2] = event.values[2];
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int legacyType = event.sensor.getLegacyType();
16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mapSensorDataToWindow(legacyType, v, SensorManager.getRotation());
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mSensors & SENSOR_ORIENTATION_RAW)!=0) {
16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTarget.onSensorChanged(SENSOR_ORIENTATION_RAW, v);
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mSensors & SENSOR_ORIENTATION)!=0) {
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    v[0] = mYawfilter.filter(event.timestamp, v[0]);
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTarget.onSensorChanged(SENSOR_ORIENTATION, v);
16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTarget.onSensorChanged(legacyType, v);
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Helper function to convert the specified sensor's data to the windows's
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * coordinate space from the device's coordinate space.
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * output: 3,4,5: values in the old API format
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *         0,1,2: transformed values in the old API format
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private void mapSensorDataToWindow(int sensor,
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float[] values, int orientation) {
16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x = values[0];
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float y = values[1];
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float z = values[2];
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (sensor) {
17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ORIENTATION:
17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ORIENTATION_RAW:
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    z = -z;
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ACCELEROMETER:
17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x = -x;
17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y = -y;
17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    z = -z;
17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_MAGNETIC_FIELD:
17119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x = -x;
17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y = -y;
17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
17149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = x;
17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = y;
17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = z;
17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[3] = x;
17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[4] = y;
17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[5] = z;
17217895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian
17227895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian            if ((orientation & Surface.ROTATION_90) != 0) {
17237895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                // handles 90 and 270 rotation
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                switch (sensor) {
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ACCELEROMETER:
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_MAGNETIC_FIELD:
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[0] =-y;
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[1] = x;
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[2] = z;
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ORIENTATION:
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ORIENTATION_RAW:
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[0] = x + ((x < 270) ? 90 : -270);
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[1] = z;
17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[2] = y;
17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17397895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian            if ((orientation & Surface.ROTATION_180) != 0) {
17407895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                x = values[0];
17417895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                y = values[1];
17427895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                z = values[2];
17437895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                // handles 180 (flip) and 270 (flip + 90) rotation
17447895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                switch (sensor) {
17457895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_ACCELEROMETER:
17467895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_MAGNETIC_FIELD:
17477895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[0] =-x;
17487895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[1] =-y;
17497895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[2] = z;
17507895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        break;
17517895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_ORIENTATION:
17527895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_ORIENTATION_RAW:
17537895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[0] = (x >= 180) ? (x - 180) : (x + 180);
17547895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[1] =-y;
17557895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[2] =-z;
17567895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        break;
17577895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                }
17587895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian            }
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17610f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian
17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class LmsFilter {
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final int SENSORS_RATE_MS = 20;
17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final int COUNT = 12;
17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final float PREDICTION_RATIO = 1.0f/3.0f;
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final float PREDICTION_TIME = (SENSORS_RATE_MS*COUNT/1000.0f)*PREDICTION_RATIO;
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mV[] = new float[COUNT*2];
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mT[] = new float[COUNT*2];
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mIndex;
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public LmsFilter() {
17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIndex = COUNT;
17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public float filter(long time, float in) {
17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float v = in;
17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float ns = 1.0f / 1000000000.0f;
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float t = time*ns;
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float v1 = mV[mIndex];
17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((v-v1) > 180) {
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                v -= 360;
17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if ((v1-v) > 180) {
17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                v += 360;
17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* Manage the circular buffer, we write the data twice spaced
17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * by COUNT values, so that we don't have to copy the array
17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * when it's full
17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIndex++;
17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIndex >= COUNT*2)
17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mIndex = COUNT;
17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mV[mIndex] = v;
17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mT[mIndex] = t;
17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mV[mIndex-COUNT] = v;
17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mT[mIndex-COUNT] = t;
17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float A, B, C, D, E;
17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float a, b;
17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int i;
18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            A = B = C = D = E = 0;
18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (i=0 ; i<COUNT-1 ; i++) {
18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int j = mIndex - 1 - i;
18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float Z = mV[j];
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float T = 0.5f*(mT[j] + mT[j+1]) - t;
18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float dT = mT[j] - mT[j+1];
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dT *= dT;
18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                A += Z*dT;
18099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                B += T*(T*dT);
18109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                C +=   (T*dT);
18119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                D += Z*(T*dT);
18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                E += dT;
18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            b = (A*B + C*D) / (E*B + C*C);
18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            a = (E*b - A) / C;
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float f = b + PREDICTION_TIME*a;
18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Normalize
18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f *= (1.0f / 360.0f);
18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (((f>=0)?f:-f) >= 0.5f)
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                f = f - (float)Math.ceil(f + 0.5f) + 1.0f;
18229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (f < 0)
18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                f += 1.0f;
18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f *= 360.0f;
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return f;
18269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18290f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian
18307a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell    /** Helper function to compute the angle change between two rotation matrices.
18317a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *  Given a current rotation matrix (R) and a previous rotation matrix
18327a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *  (prevR) computes the rotation around the x,y, and z axes which
18337a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *  transforms prevR to R.
18347a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *  outputs a 3 element vector containing the x,y, and z angle
18357a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *  change at indexes 0, 1, and 2 respectively.
18367a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     * <p> Each input matrix is either as a 3x3 or 4x4 row-major matrix
18377a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     * depending on the length of the passed array:
18387a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     * <p>If the array length is 9, then the array elements represent this matrix
18397a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     * <pre>
18407a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *   /  R[ 0]   R[ 1]   R[ 2]   \
18417a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *   |  R[ 3]   R[ 4]   R[ 5]   |
18427a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *   \  R[ 6]   R[ 7]   R[ 8]   /
18437a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *</pre>
18447a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     * <p>If the array length is 16, then the array elements represent this matrix
18457a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     * <pre>
18467a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *   /  R[ 0]   R[ 1]   R[ 2]   R[ 3]  \
18477a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *   |  R[ 4]   R[ 5]   R[ 6]   R[ 7]  |
18487a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *   |  R[ 8]   R[ 9]   R[10]   R[11]  |
18497a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *   \  R[12]   R[13]   R[14]   R[15]  /
18507a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *</pre>
18517a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     * @param R current rotation matrix
18527a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     * @param prevR previous rotation matrix
18537a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     * @param angleChange an array of floats in which the angle change is stored
18547a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     */
18557a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
18567a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell    public static void getAngleChange( float[] angleChange, float[] R, float[] prevR) {
18577a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float rd1=0,rd4=0, rd6=0,rd7=0, rd8=0;
18587a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float ri0=0,ri1=0,ri2=0,ri3=0,ri4=0,ri5=0,ri6=0,ri7=0,ri8=0;
18597a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float pri0=0, pri1=0, pri2=0, pri3=0, pri4=0, pri5=0, pri6=0, pri7=0, pri8=0;
18607a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        int i, j, k;
18617a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
18627a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        if(R.length == 9) {
18637a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri0 = R[0];
18647a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri1 = R[1];
18657a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri2 = R[2];
18667a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri3 = R[3];
18677a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri4 = R[4];
18687a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri5 = R[5];
18697a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri6 = R[6];
18707a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri7 = R[7];
18717a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri8 = R[8];
18727a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        } else if(R.length == 16) {
18737a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri0 = R[0];
18747a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri1 = R[1];
18757a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri2 = R[2];
18767a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri3 = R[4];
18777a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri4 = R[5];
18787a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri5 = R[6];
18797a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri6 = R[8];
18807a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri7 = R[9];
18817a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            ri8 = R[10];
18827a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        }
18837a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
18847a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        if(prevR.length == 9) {
188534884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri0 = prevR[0];
188634884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri1 = prevR[1];
188734884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri2 = prevR[2];
188834884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri3 = prevR[3];
188934884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri4 = prevR[4];
189034884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri5 = prevR[5];
189134884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri6 = prevR[6];
189234884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri7 = prevR[7];
189334884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri8 = prevR[8];
18947a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        } else if(prevR.length == 16) {
189534884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri0 = prevR[0];
189634884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri1 = prevR[1];
189734884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri2 = prevR[2];
189834884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri3 = prevR[4];
189934884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri4 = prevR[5];
190034884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri5 = prevR[6];
190134884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri6 = prevR[8];
190234884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri7 = prevR[9];
190334884b409e24c1183b6be4f0611b8ea22e62dc10Kevin Powell            pri8 = prevR[10];
19047a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        }
19057a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
19067a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        // calculate the parts of the rotation difference matrix we need
19077a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        // rd[i][j] = pri[0][i] * ri[0][j] + pri[1][i] * ri[1][j] + pri[2][i] * ri[2][j];
19087a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
19097a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        rd1 = pri0 * ri1 + pri3 * ri4 + pri6 * ri7; //rd[0][1]
19107a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        rd4 = pri1 * ri1 + pri4 * ri4 + pri7 * ri7; //rd[1][1]
19117a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        rd6 = pri2 * ri0 + pri5 * ri3 + pri8 * ri6; //rd[2][0]
19127a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1]
19137a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2]
19147a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
19157a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        angleChange[0] = (float)Math.atan2(rd1, rd4);
19167a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        angleChange[1] = (float)Math.asin(-rd7);
19177a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        angleChange[2] = (float)Math.atan2(-rd6, rd8);
19187a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
19197a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell    }
19207a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
19217a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell    /** Helper function to convert a rotation vector to a rotation matrix.
19227a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *  Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a
19237a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *  9  or 16 element rotation matrix in the array R.  R must have length 9 or 16.
19247a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *  If R.length == 9, the following matrix is returned:
19257a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     * <pre>
19267a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *   /  R[ 0]   R[ 1]   R[ 2]   \
19277a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *   |  R[ 3]   R[ 4]   R[ 5]   |
19287a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *   \  R[ 6]   R[ 7]   R[ 8]   /
19297a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *</pre>
19307a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     * If R.length == 16, the following matrix is returned:
19317a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     * <pre>
19327a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *   /  R[ 0]   R[ 1]   R[ 2]   0  \
19337a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *   |  R[ 4]   R[ 5]   R[ 6]   0  |
19347a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *   |  R[ 8]   R[ 9]   R[10]   0  |
19357a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *   \  0       0       0       1  /
19367a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *</pre>
19377a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *  @param rotationVector the rotation vector to convert
19387a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *  @param R an array of floats in which to store the rotation matrix
19397a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     */
19407a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell    public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) {
19417badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian
19427badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian        float q0;
19437a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float q1 = rotationVector[0];
19447a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float q2 = rotationVector[1];
19457a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float q3 = rotationVector[2];
19467a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
19477badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian        if (rotationVector.length == 4) {
19487badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian            q0 = rotationVector[3];
19497badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian        } else {
19507badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian            q0 = (float)Math.sqrt(1 - q1*q1 - q2*q2 - q3*q3);
19517badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian        }
19527badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian
19537a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float sq_q1 = 2 * q1 * q1;
19547a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float sq_q2 = 2 * q2 * q2;
19557a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float sq_q3 = 2 * q3 * q3;
19567a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float q1_q2 = 2 * q1 * q2;
19577a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float q3_q0 = 2 * q3 * q0;
19587a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float q1_q3 = 2 * q1 * q3;
19597a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float q2_q0 = 2 * q2 * q0;
19607a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float q2_q3 = 2 * q2 * q3;
19617a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        float q1_q0 = 2 * q1 * q0;
19627a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
19637a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        if(R.length == 9) {
19647a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[0] = 1 - sq_q2 - sq_q3;
19657a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[1] = q1_q2 - q3_q0;
19667a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[2] = q1_q3 + q2_q0;
19677a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
19687a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[3] = q1_q2 + q3_q0;
19697a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[4] = 1 - sq_q1 - sq_q3;
19707a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[5] = q2_q3 - q1_q0;
19717a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
19727a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[6] = q1_q3 - q2_q0;
19737a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[7] = q2_q3 + q1_q0;
19747a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[8] = 1 - sq_q1 - sq_q2;
19757a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        } else if (R.length == 16) {
19767a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[0] = 1 - sq_q2 - sq_q3;
19777a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[1] = q1_q2 - q3_q0;
19787a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[2] = q1_q3 + q2_q0;
19797a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[3] = 0.0f;
19807a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
19817a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[4] = q1_q2 + q3_q0;
19827a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[5] = 1 - sq_q1 - sq_q3;
19837a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[6] = q2_q3 - q1_q0;
19847a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[7] = 0.0f;
19857a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
19867a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[8] = q1_q3 - q2_q0;
19877a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[9] = q2_q3 + q1_q0;
19887a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[10] = 1 - sq_q1 - sq_q2;
19897a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[11] = 0.0f;
19907a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
19917a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[12] = R[13] = R[14] = 0.0f;
19927a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell            R[15] = 1.0f;
19937a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        }
19947a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell    }
19957a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
19967a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell    /** Helper function to convert a rotation vector to a normalized quaternion.
19977a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *  Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a normalized
19987a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *  quaternion in the array Q.  The quaternion is stored as [w, x, y, z]
19997a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *  @param rv the rotation vector to convert
20007a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     *  @param Q an array of floats in which to store the computed quaternion
20017a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     */
20027a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell    public static void getQuaternionFromVector(float[] Q, float[] rv) {
20037badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian        if (rv.length == 4) {
20047badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian            Q[0] = rv[3];
20057badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian        } else {
20067badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian            //In this case, the w component of the quaternion is known to be a positive number
20077badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian            Q[0] = (float)Math.sqrt(1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2]);
20087badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian        }
20097a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        Q[1] = rv[0];
20107a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        Q[2] = rv[1];
20117a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        Q[3] = rv[2];
20127a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell    }
20137a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
20149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void nativeClassInit();
20159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native int sensors_module_init();
20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native int sensors_module_get_next_sensor(Sensor sensor, int next);
20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Used within this module from outside SensorManager, don't make private
20201bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    static native int sensors_create_queue();
20211bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    static native void sensors_destroy_queue(int queue);
20221bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    static native boolean sensors_enable_sensor(int queue, String name, int sensor, int enable);
20231bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    static native int sensors_data_poll(int queue, float[] values, int[] status, long[] timestamp);
20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2025