SensorManager.java revision 74cde2cee9e53006a710f4e80700cd560c2d0e4d
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.content.Context;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
21270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwoodimport android.os.Bundle;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper;
23270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwoodimport android.os.Parcelable;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ParcelFileDescriptor;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseArray;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IRotationWatcher;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowManager;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Surface;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collections;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
4474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * SensorManager lets you access the device's {@link android.hardware.Sensor
4574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * sensors}. Get an instance of this class by calling
4674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * {@link android.content.Context#getSystemService(java.lang.String)
4774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * Context.getSystemService()} with the argument
4874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * {@link android.content.Context#SENSOR_SERVICE}.
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
50287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopianpublic class SensorManager
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "SensorManager";
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final float[] mTempMatrix = new float[16];
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* NOTE: sensor IDs must be a power of 2 */
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an orientation sensor. See
5974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
6074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ORIENTATION = 1 << 0;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an accelerometer. See
6874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
6974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ACCELEROMETER = 1 << 1;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a temperature sensor See
7774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
7874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_TEMPERATURE = 1 << 2;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a magnetic sensor See
8674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
8774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MAGNETIC_FIELD = 1 << 3;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an ambient light sensor See
9574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
9674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_LIGHT = 1 << 4;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a proximity sensor See
10474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
10574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_PROXIMITY = 1 << 5;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a Tricorder See
11374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
11474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_TRICORDER = 1 << 6;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an orientation sensor. See
12274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
12374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
13074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant that includes all sensors
13174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
1324a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1334a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ALL = 0x7F;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
13874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Smallest sensor ID
13974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
1404a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1414a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MIN = SENSOR_ORIENTATION;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
14674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Largest sensor ID
14774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
1484a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1494a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1);
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
15574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the X value in the array returned by
1564a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
15774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
1584a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1594a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DATA_X = 0;
16274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
16374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
16474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the Y value in the array returned by
1654a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
16674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias 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 DATA_Y = 1;
17174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
17274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
17374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the Z value in the array returned by
1744a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
17574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
1764a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1774a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DATA_Z = 2;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
18274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Offset to the untransformed values in the array returned by
1834a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
18474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
1854a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1864a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_INDEX = 3;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
19174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed X value in the array returned by
1924a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
19374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
1944a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1954a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_X = 3;
19874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
19974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
20074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed Y value in the array returned by
2014a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
20274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
2034a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2044a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_Y = 4;
20774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
20874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
20974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed Z value in the array returned by
2104a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
21174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
2124a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2134a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_Z = 5;
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Standard gravity (g) on Earth. This value is equivalent to 1G */
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float STANDARD_GRAVITY = 9.80665f;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Sun's gravity in SI units (m/s^2) */
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_SUN             = 275.0f;
22274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Mercury's gravity in SI units (m/s^2) */
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MERCURY         = 3.70f;
22474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Venus' gravity in SI units (m/s^2) */
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_VENUS           = 8.87f;
22674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Earth's gravity in SI units (m/s^2) */
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_EARTH           = 9.80665f;
22874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** The Moon's gravity in SI units (m/s^2) */
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MOON            = 1.6f;
23074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Mars' gravity in SI units (m/s^2) */
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MARS            = 3.71f;
23274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Jupiter's gravity in SI units (m/s^2) */
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_JUPITER         = 23.12f;
23474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Saturn's gravity in SI units (m/s^2) */
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_SATURN          = 8.96f;
23674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Uranus' gravity in SI units (m/s^2) */
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_URANUS          = 8.69f;
23874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Neptune's gravity in SI units (m/s^2) */
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_NEPTUNE         = 11.0f;
24074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Pluto's gravity in SI units (m/s^2) */
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_PLUTO           = 0.6f;
24274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_DEATH_STAR_I    = 0.000000353036145f;
24474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Gravity on the island */
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_THE_ISLAND      = 4.815162342f;
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Maximum magnetic field on Earth's surface */
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Minimum magnetic field on Earth's surface */
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
25474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Maximum luminance of sunlight in lux */
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
25674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance of sunlight in lux */
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNLIGHT     = 110000.0f;
25874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance in shade in lux */
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SHADE        = 20000.0f;
26074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance under an overcast sky in lux */
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_OVERCAST     = 10000.0f;
26274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at sunrise in lux */
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNRISE      = 400.0f;
26474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance under a cloudy sky in lux */
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_CLOUDY       = 100.0f;
26674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at night with full moon in lux */
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_FULLMOON     = 0.25f;
26874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at night with no moon in lux*/
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_NO_MOON      = 0.001f;
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** get sensor data as fast as possible */
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_FASTEST = 0;
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate suitable for games */
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_GAME = 1;
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate suitable for the user interface  */
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_UI = 2;
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate (default) suitable for screen orientation changes */
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_NORMAL = 3;
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
28374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The values returned by this sensor cannot be trusted, calibration is
28474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * needed or the environment doesn't allow readings
28574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_UNRELIABLE = 0;
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
28974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This sensor is reporting data with low accuracy, calibration with the
29074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * environment is needed
29174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
29574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This sensor is reporting data with an average level of accuracy,
29674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * calibration with the environment may improve the readings
29774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** This sensor is reporting data with maximum accuracy */
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_X = 1;
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_Y = 2;
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_Z = 3;
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_X = AXIS_X | 0x80;
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_Y = AXIS_Y | 0x80;
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_Z = AXIS_Z | 0x80;
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ISensorService mSensorService;
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Looper mMainLooper;
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("deprecation")
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<SensorListener, LegacyListener> mLegacyListenersMap =
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<SensorListener, LegacyListener>();
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int SENSOR_DISABLE = -1;
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean sSensorModuleInitialized = false;
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static SparseArray<List<Sensor>> sSensorListByType = new SparseArray<List<Sensor>>();
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static IWindowManager sWindowManager;
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int sRotation = Surface.ROTATION_0;
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* The thread and the sensor list are global to the process
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * but the actual thread is spawned on demand */
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static SensorThread sSensorThread;
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Used within this module from outside SensorManager, don't make private
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final ArrayList<ListenerDelegate> sListeners =
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new ArrayList<ListenerDelegate>();
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static private class SensorThread {
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Thread mThread;
346b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian        boolean mSensorsReady;
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SensorThread() {
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // this gets to the sensor module. We can have only one per process.
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sensors_data_init();
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected void finalize() {
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sensors_data_uninit();
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // must be called with sListeners lock
359b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian        boolean startLocked(ISensorService service) {
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mThread == null) {
362270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                    Bundle dataChannel = service.getDataChannel();
363b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                    if (dataChannel != null) {
364b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                        mSensorsReady = false;
365b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                        SensorThreadRunnable runnable = new SensorThreadRunnable(dataChannel);
366b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                        Thread thread = new Thread(runnable, SensorThread.class.getName());
367b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                        thread.start();
368b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                        synchronized (runnable) {
369b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                            while (mSensorsReady == false) {
370b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                                runnable.wait();
371b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                            }
372b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                        }
373b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                        mThread = thread;
374b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                    }
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "RemoteException in startLocked: ", e);
378b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian            } catch (InterruptedException e) {
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
380b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian            return mThread == null ? false : true;
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private class SensorThreadRunnable implements Runnable {
384270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood            private Bundle mDataChannel;
385270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood            SensorThreadRunnable(Bundle dataChannel) {
386270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                mDataChannel = dataChannel;
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
388270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood
389270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood            private boolean open() {
390b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                // NOTE: this cannot synchronize on sListeners, since
391b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                // it's held in the main thread at least until we
392b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                // return from here.
393270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood
394270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                // this thread is guaranteed to be unique
395270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                Parcelable[] pfds = mDataChannel.getParcelableArray("fds");
396270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                FileDescriptor[] fds;
397270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                if (pfds != null) {
398270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                    int length = pfds.length;
399270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                    fds = new FileDescriptor[length];
400270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                    for (int i = 0; i < length; i++) {
401270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                        ParcelFileDescriptor pfd = (ParcelFileDescriptor)pfds[i];
402270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                        fds[i] = pfd.getFileDescriptor();
403270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                    }
404270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                } else {
405270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                    fds = null;
406270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                }
407270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                int[] ints = mDataChannel.getIntArray("ints");
408270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                sensors_data_open(fds, ints);
409270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                if (pfds != null) {
410270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                    try {
411270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                        // close our copies of the file descriptors,
412270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                        // since we are just passing these to the JNI code and not using them here.
413270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                        for (int i = pfds.length - 1; i >= 0; i--) {
414270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                            ParcelFileDescriptor pfd = (ParcelFileDescriptor)pfds[i];
415270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                            pfd.close();
416270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                        }
417270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                    } catch (IOException e) {
418270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                        // *shrug*
419270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                        Log.e(TAG, "IOException: ", e);
420270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                    }
421270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                }
422270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood                mDataChannel = null;
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
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final int sensor = sensors_data_poll(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()) {
4506dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                            if (sensor == -1) {
4516dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                                // we lost the connection to the event stream. this happens
4526dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                                // when the last listener is removed.
4536dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                                Log.d(TAG, "_sensors_data_poll() failed, we bail out.");
4546dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                            }
4556dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber
4566dee6243bf5ecb96291e62ece7d736c5aee1e505Andreas Huber                            // we have no more listeners or polling failed, terminate the thread
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            sensors_data_close();
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mThread = null;
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            break;
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        final Sensor sensorObject = sHandleToSensor.get(sensor);
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (sensorObject != null) {
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // report the sensor event to all listeners that
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // care about it.
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            final int size = sListeners.size();
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            for (int i=0 ; i<size ; i++) {
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                ListenerDelegate listener = sListeners.get(i);
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (listener.hasSensor(sensorObject)) {
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    // this is asynchronous (okay to call
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    // with sListeners lock held).
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    listener.onSensorChangedLocked(sensorObject,
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            values, timestamp, accuracy);
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
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                //Log.d(TAG, "exiting main sensor thread");
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
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    private class ListenerDelegate extends Binder {
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final SensorEventListener mSensorEventListener;
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final Handler mHandler;
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private SensorEvent mValuesPool;
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int mSensors;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) {
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensorEventListener = listener;
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // currently we create one Handler instance per listener, but we could
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // have one per looper (we'd need to pass the ListenerDelegate
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // instance to handleMessage and keep track of them separately).
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler = new Handler(looper) {
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                @Override
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                public void handleMessage(Message msg) {
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SensorEvent t = (SensorEvent)msg.obj;
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.accuracy >= 0) {
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy);
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mSensorEventListener.onSensorChanged(t);
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    returnToPool(t);
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            };
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            addSensor(sensor);
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected SensorEvent createSensorEvent() {
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // maximal size for all legacy events is 3
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new SensorEvent(3);
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected SensorEvent getFromPool() {
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorEvent t = null;
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // remove the array from the pool
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                t = mValuesPool;
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mValuesPool = null;
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (t == null) {
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // the pool was empty, we need a new one
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                t = createSensorEvent();
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return t;
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected void returnToPool(SensorEvent t) {
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // put back the array into the pool
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mValuesPool == null) {
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mValuesPool = t;
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Object getListener() {
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSensorEventListener;
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int addSensor(Sensor sensor) {
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors |= 1<<sensor.getHandle();
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensorList.add(sensor);
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSensors;
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int removeSensor(Sensor sensor) {
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors &= ~(1<<sensor.getHandle());
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensorList.remove(sensor);
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSensors;
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean hasSensor(Sensor sensor) {
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ((mSensors & (1<<sensor.getHandle())) != 0);
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        mSensorService = ISensorService.Stub.asInterface(
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ServiceManager.getService(Context.SENSOR_SERVICE));
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMainLooper = mainLooper;
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(sListeners) {
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!sSensorModuleInitialized) {
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sSensorModuleInitialized = true;
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                nativeClassInit();
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sWindowManager = IWindowManager.Stub.asInterface(
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ServiceManager.getService("window"));
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (sWindowManager != null) {
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // if it's null we're running in the system process
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // which won't get the rotated values
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
598287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                        sRotation = sWindowManager.watchRotation(
599287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                            new IRotationWatcher.Stub() {
600287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                                public void onRotationChanged(int rotation) {
601287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                                    SensorManager.this.onRotationChanged(rotation);
602287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                                }
603287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                            }
604287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                        );
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // initialize the sensor list
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sensors_module_init();
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final ArrayList<Sensor> fullList = sFullSensorsList;
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int i = 0;
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Sensor sensor = new Sensor();
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i = sensors_module_get_next_sensor(sensor, i);
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (i>=0) {
618f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato                        //Log.d(TAG, "found sensor: " + sensor.getName() +
619f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato                        //        ", handle=" + sensor.getHandle());
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sensor.setLegacyType(getLegacySensorType(sensor.getType()));
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fullList.add(sensor);
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sHandleToSensor.append(sensor.getHandle(), sensor);
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } while (i>0);
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sSensorThread = new SensorThread();
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getLegacySensorType(int type) {
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (type) {
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_ACCELEROMETER:
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_ACCELEROMETER;
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_MAGNETIC_FIELD:
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_MAGNETIC_FIELD;
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_ORIENTATION:
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_ORIENTATION_RAW;
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_TEMPERATURE:
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_TEMPERATURE;
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
64574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
64674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return available sensors.
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
64874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#getSensorList(int)} instead
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getSensors() {
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int result = 0;
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ArrayList<Sensor> fullList = sFullSensorsList;
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (Sensor i : fullList) {
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (i.getType()) {
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_ACCELEROMETER:
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_ACCELEROMETER;
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_MAGNETIC_FIELD:
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_MAGNETIC_FIELD;
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_ORIENTATION:
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_ORIENTATION |
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    SensorManager.SENSOR_ORIENTATION_RAW;
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
67274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Use this method to get the list of available sensors of a certain type.
67374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Make multiple calls to get sensors of different types or use
67474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the
67574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * sensors.
67674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
67774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param type
67874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        of sensors requested
67974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a list of sensors matching the asked type.
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<Sensor> getSensorList(int type) {
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // cache the returned lists the first time
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> list;
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ArrayList<Sensor> fullList = sFullSensorsList;
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(fullList) {
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            list = sSensorListByType.get(type);
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (list == null) {
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (type == Sensor.TYPE_ALL) {
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    list = fullList;
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    list = new ArrayList<Sensor>();
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (Sensor i : fullList) {
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (i.getType() == type)
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            list.add(i);
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                list = Collections.unmodifiableList(list);
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sSensorListByType.append(type, list);
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return list;
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
70674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Use this method to get the default sensor for a given type. Note that the
70774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * returned sensor could be a composite sensor, and its data could be
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * averaged or filtered. If you need to access the raw sensors use
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link SensorManager#getSensorList(int) getSensorList}.
71074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
71174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param type
71274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        of sensors requested
71374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the default sensors matching the asked type.
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Sensor getDefaultSensor(int type) {
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: need to be smarter, for now, just return the 1st sensor
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> l = getSensorList(type);
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return l.isEmpty() ? null : l.get(0);
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registers a listener for given sensors.
72474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
72674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
72774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
72874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
72974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
73074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        sensor listener object
73174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
73274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensors
73374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a bit masks of the sensors to register to
73474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
73574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> if the sensor is supported and successfully
73674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorListener listener, int sensors) {
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registers a SensorListener for given sensors.
74574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
74774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
74874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
74974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
75074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
75174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        sensor listener object
75274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
75374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensors
75474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a bit masks of the sensors to register to
75574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
75674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param rate
75774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        rate of events. This is only a hint to the system. events may be
75874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
75974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
76074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
76174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
76274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
76374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> if the sensor is supported and successfully
76474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorListener listener, int sensors, int rate) {
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result = false;
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("deprecation")
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean registerLegacyListener(int legacyType, int type,
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorListener listener, int sensors, int rate)
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result = false;
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Are we activating this legacy sensor?
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((sensors & legacyType) != 0) {
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // if so, find a suitable Sensor
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Sensor sensor = getDefaultSensor(type);
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sensor != null) {
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If we don't already have one, create a LegacyListener
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // to wrap this listener and process the events as
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // they are expected by legacy apps.
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                LegacyListener legacyListener = null;
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                synchronized (mLegacyListenersMap) {
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    legacyListener = mLegacyListenersMap.get(listener);
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (legacyListener == null) {
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // we didn't find a LegacyListener for this client,
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // create one, and put it in our list.
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        legacyListener = new LegacyListener(listener);
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mLegacyListenersMap.put(listener, legacyListener);
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // register this legacy sensor with this legacy listener
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                legacyListener.registerSensor(legacyType);
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // and finally, register the legacy listener with the new apis
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                result = registerListener(legacyListener, sensor, rate);
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for the sensors with which it is registered.
82274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
82474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#unregisterListener(SensorEventListener, Sensor)}
82574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
82674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
82774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
82874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
82974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
83074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensors
83174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a bit masks of the sensors to unregister from
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorListener listener, int sensors) {
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("deprecation")
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void unregisterLegacyListener(int legacyType, int type,
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorListener listener, int sensors)
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // do we know about this listener?
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LegacyListener legacyListener = null;
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mLegacyListenersMap) {
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            legacyListener = mLegacyListenersMap.get(listener);
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (legacyListener != null) {
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Are we deactivating this legacy sensor?
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((sensors & legacyType) != 0) {
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // if so, find the corresponding Sensor
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Sensor sensor = getDefaultSensor(type);
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (sensor != null) {
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // unregister this legacy sensor and if we don't
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // need the corresponding Sensor, unregister it too
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (legacyListener.unregisterSensor(legacyType)) {
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // corresponding sensor not needed, unregister
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        unregisterListener(legacyListener, sensor);
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // finally check if we still need the legacyListener
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // in our mapping, if not, get rid of it too.
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        synchronized(sListeners) {
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            boolean found = false;
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            for (ListenerDelegate i : sListeners) {
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (i.getListener() == legacyListener) {
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    found = true;
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    break;
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (!found) {
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                synchronized (mLegacyListenersMap) {
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    mLegacyListenersMap.remove(listener);
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
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     * Unregisters a listener for all sensors.
89474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
89674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#unregisterListener(SensorEventListener)}
89774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
89874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
89974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
90074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorListener listener) {
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for the sensors with which it is registered.
90974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
91074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
91174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorEventListener object
91274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
91374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the sensor to unregister from
91474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorEventListener listener, Sensor sensor) {
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterListener((Object)listener, sensor);
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for all sensors.
92274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
92374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
92474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
92574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorEventListener listener) {
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterListener((Object)listener);
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
93274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Registers a {@link android.hardware.SensorEventListener
93374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * SensorEventListener} for the given sensor.
93474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
93574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
93674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        A {@link android.hardware.SensorEventListener SensorEventListener}
93774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        object.
93874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
93974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
94074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.hardware.Sensor Sensor} to register to.
94174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
94274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param rate
94374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The rate {@link android.hardware.SensorEvent sensor events} are
94474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered at. This is only a hint to the system. Events may be
94574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
94674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
94774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
94874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
94974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
95074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> if the sensor is supported and successfully
95174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled.
95274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return registerListener(listener, sensor, rate, null);
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
95974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Registers a {@link android.hardware.SensorEventListener
96074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * SensorEventListener} for the given sensor.
96174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
96274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
96374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        A {@link android.hardware.SensorEventListener SensorEventListener}
96474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        object.
96574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
96674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
96774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.hardware.Sensor Sensor} to register to.
96874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
96974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param rate
97074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The rate {@link android.hardware.SensorEvent sensor events} are
97174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered at. This is only a hint to the system. Events may be
97274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
97374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
97474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
97574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
97674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
97774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param handler
97874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.os.Handler Handler} the
97974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent sensor events} will be
98074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered to.
98174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the sensor is supported and successfully enabled.
98374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Handler handler) {
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null || sensor == null) {
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result;
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int delay = -1;
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (rate) {
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_FASTEST:
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delay = 0;
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_GAME:
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delay = 20;
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_UI:
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delay = 60;
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_NORMAL:
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delay = 200;
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (sListeners) {
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ListenerDelegate l = null;
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (ListenerDelegate i : sListeners) {
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (i.getListener() == listener) {
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        l = i;
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String name = sensor.getName();
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int handle = sensor.getHandle();
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (l == null) {
1022b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                    result = false;
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    l = new ListenerDelegate(listener, sensor, handler);
1024b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                    sListeners.add(l);
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!sListeners.isEmpty()) {
1026b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                        result = sSensorThread.startLocked(mSensorService);
1027b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                        if (result) {
1028b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                            result = mSensorService.enableSensor(l, name, handle, delay);
1029b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                            if (!result) {
1030b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                                // there was an error, remove the listeners
1031b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                                sListeners.remove(l);
1032b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                            }
1033b3dc5eb4e4143b119491a05e89b186763979ef75Mathias Agopian                        }
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result = mSensorService.enableSensor(l, name, handle, delay);
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (result) {
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        l.addSensor(sensor);
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "RemoteException in registerListener: ", e);
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            result = false;
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void unregisterListener(Object listener, Sensor sensor) {
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null || sensor == null) {
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (sListeners) {
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int size = sListeners.size();
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i=0 ; i<size ; i++) {
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ListenerDelegate l = sListeners.get(i);
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (l.getListener() == listener) {
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // disable these sensors
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        String name = sensor.getName();
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int handle = sensor.getHandle();
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // if we have no more sensors enabled on this listener,
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // take it off the list.
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (l.removeSensor(sensor) == 0) {
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            sListeners.remove(i);
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "RemoteException in unregisterListener: ", e);
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void unregisterListener(Object listener) {
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (sListeners) {
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int size = sListeners.size();
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i=0 ; i<size ; i++) {
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ListenerDelegate l = sListeners.get(i);
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (l.getListener() == listener) {
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // disable all sensors for this listener
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        for (Sensor sensor : l.getSensors()) {
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            String name = sensor.getName();
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            int handle = sensor.getHandle();
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sListeners.remove(i);
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "RemoteException in unregisterListener: ", e);
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
110474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
110574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Computes the inclination matrix <b>I</b> as well as the rotation matrix
110674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>R</b> transforming a vector from the device coordinate system to the
110774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * world's coordinate system which is defined as a direct orthonormal basis,
110874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * where:
110974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
111174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the ground at the device's current location and roughly points East).</li>
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Y is tangential to the ground at the device's current location and
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * points towards the magnetic North Pole.</li>
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Z points towards the sky and is perpendicular to the ground.</li>
111774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
112074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
112174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * By definition:
112274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
112374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * [0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity)
112474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
112574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * [0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b> (m = magnitude of
112674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * geomagnetic field)
112774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
112874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>R</b> is the identity matrix when the device is aligned with the
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * world's coordinate system, that is, when the device's X axis points
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * toward East, the Y axis points to the North Pole and the device is facing
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the sky.
113274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
113374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
113474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>I</b> is a rotation matrix transforming the geomagnetic vector into
113574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * the same coordinate space as gravity (the world's coordinate space).
113674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>I</b> is a simple rotation around the X axis. The inclination angle in
113774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * radians can be computed with {@link #getInclination}.
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
114074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
114174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Each matrix is returned either as a 3x3 or 4x4 row-major matrix depending
114274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * on the length of the passed array:
114374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
114474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>If the array length is 16:</u>
114574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]   M[ 3]  \
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 4]   M[ 5]   M[ 6]   M[ 7]  |
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 8]   M[ 9]   M[10]   M[11]  |
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \  M[12]   M[13]   M[14]   M[15]  /
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
115274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
115374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This matrix is ready to be used by OpenGL ES's
115474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int)
115574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * glLoadMatrixf(float[], int)}.
115674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
115774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Note that because OpenGL matrices are column-major matrices you must
115874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * transpose the matrix before using it. However, since the matrix is a
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rotation matrix, its transpose is also its inverse, conveniently, it is
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * often the inverse of the rotation that is needed for rendering; it can
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * therefore be used with OpenGL ES directly.
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Also note that the returned matrices always have this form:
116474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]   0  \
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 4]   M[ 5]   M[ 6]   0  |
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 8]   M[ 9]   M[10]   0  |
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \      0       0       0   1  /
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
117174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
117274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
117374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>If the array length is 9:</u>
117474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]  \
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 3]   M[ 4]   M[ 5]  |
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \  M[ 6]   M[ 7]   M[ 8]  /
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
118074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
118274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
118374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The inverse of each matrix can be computed easily by taking its
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * transpose.
118574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
118674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
118774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The matrices returned by this function are meaningful only when the
118874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * device is not free-falling and it is not close to the magnetic north. If
118974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * the device is accelerating, or placed into a strong magnetic field, the
119074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * returned matrices may be inaccurate.
119174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
119274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param R
119374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 9 floats holding the rotation matrix <b>R</b> when
119474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        this function returns. R can be null.
119574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
119674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
119774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param I
119874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 9 floats holding the rotation matrix <b>I</b> when
119974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        this function returns. I can be null.
120074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
120174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
120274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param gravity
120374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 3 floats containing the gravity vector expressed in
120474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the device's coordinate. You can simply use the
120574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent#values values} returned by a
120674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent SensorEvent} of a
120774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor Sensor} of type
120874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor#TYPE_ACCELEROMETER
120974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        TYPE_ACCELEROMETER}.
121074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
121174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
121274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param geomagnetic
121374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 3 floats containing the geomagnetic vector
121474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        expressed in the device's coordinate. You can simply use the
121574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent#values values} returned by a
121674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent SensorEvent} of a
121774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor Sensor} of type
121874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD
121974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        TYPE_MAGNETIC_FIELD}.
122074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
122174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> on success, <code>false</code> on failure (for
122274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         instance, if the device is in free fall). On failure the output
122374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         matrices are not modified.
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean getRotationMatrix(float[] R, float[] I,
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] gravity, float[] geomagnetic) {
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: move this to native code for efficiency
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Ax = gravity[0];
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Ay = gravity[1];
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Az = gravity[2];
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ex = geomagnetic[0];
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ey = geomagnetic[1];
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ez = geomagnetic[2];
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hx = Ey*Az - Ez*Ay;
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hy = Ez*Ax - Ex*Az;
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hz = Ex*Ay - Ey*Ax;
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (normH < 0.1f) {
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // device is close to free fall (or in space?), or close to
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // magnetic north pole. Typical values are  > 100.
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float invH = 1.0f / normH;
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hx *= invH;
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hy *= invH;
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hz *= invH;
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Ax *= invA;
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Ay *= invA;
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Az *= invA;
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Mx = Ay*Hz - Az*Hy;
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float My = Az*Hx - Ax*Hz;
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Mz = Ax*Hy - Ay*Hx;
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (R != null) {
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (R.length == 9) {
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[0] = Hx;     R[1] = Hy;     R[2] = Hz;
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[3] = Mx;     R[4] = My;     R[5] = Mz;
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[6] = Ax;     R[7] = Ay;     R[8] = Az;
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (R.length == 16) {
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[0]  = Hx;    R[1]  = Hy;    R[2]  = Hz;   R[3]  = 0;
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[4]  = Mx;    R[5]  = My;    R[6]  = Mz;   R[7]  = 0;
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[8]  = Ax;    R[9]  = Ay;    R[10] = Az;   R[11] = 0;
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[12] = 0;     R[13] = 0;     R[14] = 0;    R[15] = 1;
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (I != null) {
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // compute the inclination matrix by projecting the geomagnetic
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // vector onto the Z (gravity) and X (horizontal component
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // of geomagnetic vector) axes.
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (I.length == 9) {
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[0] = 1;     I[1] = 0;     I[2] = 0;
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[3] = 0;     I[4] = c;     I[5] = s;
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[6] = 0;     I[7] =-s;     I[8] = c;
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (I.length == 16) {
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[0] = 1;     I[1] = 0;     I[2] = 0;
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[4] = 0;     I[5] = c;     I[6] = s;
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[8] = 0;     I[9] =-s;     I[10]= c;
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[15] = 1;
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes the geomagnetic inclination angle in radians from the
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}.
129274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
129374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param I
129474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        inclination matrix see {@link #getRotationMatrix}.
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The geomagnetic inclination angle in radians.
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static float getInclination(float[] I) {
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (I.length == 9) {
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (float)Math.atan2(I[5], I[4]);
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (float)Math.atan2(I[6], I[5]);
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
130674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
130774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Rotates the supplied rotation matrix so it is expressed in a different
130874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * coordinate system. This is typically used when an application needs to
130974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * compute the three orientation angles of the device (see
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getOrientation}) in a different coordinate system.
131174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
131274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
131374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
131474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * When the rotation matrix is used for drawing (for instance with OpenGL
131574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * ES), it usually <b>doesn't need</b> to be transformed by this function,
131674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * unless the screen is physically rotated, in which case you can use
131774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.view.Display#getRotation() Display.getRotation()} to
131874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * retrieve the current rotation of the screen. Note that because the user
131974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * is generally free to rotate their screen, you often should consider the
132074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * rotation in deciding the parameters to use here.
132174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
132274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
132374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
132474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>Examples:</u>
132574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
132674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
132774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
132874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <li>Using the camera (Y axis along the camera's axis) for an augmented
132974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * reality application where the rotation angles are needed:</li>
133074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
133174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
133274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
133374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code>
133474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
133574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13375cb70b54156fb305d579a1cc167424c8705bfdf7Dianne Hackborn     * <li>Using the device as a mechanical compass when rotation is
133874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:</li>
133974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
134074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
134174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
134274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code>
134374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
134474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
134574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
134674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Beware of the above example. This call is needed only to account for a
134774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * rotation from its natural orientation when calculating the rotation
134874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * angles (see {@link #getOrientation}). If the rotation matrix is also used
134974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * for rendering, it may not need to be transformed, for instance if your
135074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.app.Activity Activity} is running in landscape mode.
135174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
135274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
135374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
135474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Since the resulting coordinate system is orthonormal, only two axes need
135574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * to be specified.
135674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
135774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param inR
135874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the rotation matrix to be transformed. Usually it is the matrix
135974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        returned by {@link #getRotationMatrix}.
136074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
136174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param X
136274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        defines on which world axis and direction the X axis of the device
136374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is mapped.
136474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
136574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param Y
136674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        defines on which world axis and direction the Y axis of the device
136774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is mapped.
136874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
136974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param outR
137074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the transformed rotation matrix. inR and outR can be the same
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        array, but it is not recommended for performance reason.
137274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
137374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> on success. <code>false</code> if the input
137474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         parameters are incorrect, for instance if X and Y define the same
137574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         axis. Or if inR and outR don't have the same length.
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean remapCoordinateSystem(float[] inR, int X, int Y,
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] outR)
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (inR == outR) {
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float[] temp = mTempMatrix;
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(temp) {
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // we don't expect to have a lot of contention
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final int size = outR.length;
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (int i=0 ; i<size ; i++)
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        outR[i] = temp[i];
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return true;
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return remapCoordinateSystemImpl(inR, X, Y, outR);
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y,
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] outR)
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * X and Y define a rotation matrix 'r':
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *                              r[0] ^ r[1]
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * where the 3rd line is the vector product of the first 2 lines
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int length = outR.length;
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (inR.length != length)
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // invalid parameter
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((X & 0x7C)!=0 || (Y & 0x7C)!=0)
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // invalid parameter
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (((X & 0x3)==0) || ((Y & 0x3)==0))
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // no axis specified
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((X & 0x3) == (Y & 0x3))
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // same axis specified
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // this can be calculated by exclusive-or'ing X and Y; except for
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the sign inversion (+/-) which is calculated below.
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int Z = X ^ Y;
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // extract the axis (remove the sign), offset in the range 0 to 2.
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int x = (X & 0x3)-1;
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int y = (Y & 0x3)-1;
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int z = (Z & 0x3)-1;
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // compute the sign of Z (whether it needs to be inverted)
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int axis_y = (z+1)%3;
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int axis_z = (z+2)%3;
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (((x^axis_y)|(y^axis_z)) != 0)
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Z ^= 0x80;
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sx = (X>=0x80);
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sy = (Y>=0x80);
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sz = (Z>=0x80);
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Perform R * r, in avoiding actual muls and adds.
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int rowLength = ((length==16)?4:3);
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int j=0 ; j<3 ; j++) {
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int offset = j*rowLength;
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0 ; i<3 ; i++) {
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (x==i)   outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0];
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (y==i)   outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1];
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (z==i)   outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2];
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (length == 16) {
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            outR[15] = 1;
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes the device's orientation based on the rotation matrix.
145974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
146074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * When it returns, the array values is filled with the result:
146174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[0]: <i>azimuth</i>, rotation around the Z axis.</li>
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[1]: <i>pitch</i>, rotation around the X axis.</li>
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li>
146574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
1467210fc914db37b3cf77ebb3bf75b0b509a1ecb07cMathias Agopian     * All three angles above are in <b>radians</b> and <b>positive</b> in the
1468210fc914db37b3cf77ebb3bf75b0b509a1ecb07cMathias Agopian     * <b>counter-clockwise</b> direction.
146974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
147074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param R
147174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        rotation matrix see {@link #getRotationMatrix}.
147274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param values
147374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        an array of 3 floats to hold the result.
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The array values passed as argument.
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
147674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian   public static float[] getOrientation(float[] R, float values[]) {
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * 4x4 (length=16) case:
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   /  R[ 0]   R[ 1]   R[ 2]   0  \
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 4]   R[ 5]   R[ 6]   0  |
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 8]   R[ 9]   R[10]   0  |
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   \      0       0       0   1  /
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * 3x3 (length=9) case:
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   /  R[ 0]   R[ 1]   R[ 2]  \
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 3]   R[ 4]   R[ 5]  |
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   \  R[ 6]   R[ 7]   R[ 8]  /
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (R.length == 9) {
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = (float)Math.atan2(R[1], R[4]);
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = (float)Math.asin(-R[7]);
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = (float)Math.atan2(-R[6], R[8]);
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = (float)Math.atan2(R[1], R[5]);
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = (float)Math.asin(-R[9]);
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = (float)Math.atan2(-R[8], R[10]);
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return values;
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onRotationChanged(int rotation) {
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(sListeners) {
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sRotation  = rotation;
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static int getRotation() {
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(sListeners) {
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return sRotation;
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class LegacyListener implements SensorEventListener {
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mValues[] = new float[6];
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private SensorListener mTarget;
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mSensors;
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final LmsFilter mYawfilter = new LmsFilter();
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LegacyListener(SensorListener target) {
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTarget = target;
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors = 0;
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void registerSensor(int legacyType) {
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors |= legacyType;
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean unregisterSensor(int legacyType) {
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors &= ~legacyType;
15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mask = SENSOR_ORIENTATION|SENSOR_ORIENTATION_RAW;
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (((legacyType&mask)!=0) && ((mSensors&mask)!=0)) {
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onAccuracyChanged(Sensor sensor, int accuracy) {
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTarget.onAccuracyChanged(sensor.getLegacyType(), accuracy);
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (AbstractMethodError e) {
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // old app that doesn't implement this method
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // just ignore it.
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onSensorChanged(SensorEvent event) {
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float v[] = mValues;
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[0] = event.values[0];
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[1] = event.values[1];
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[2] = event.values[2];
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int legacyType = event.sensor.getLegacyType();
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mapSensorDataToWindow(legacyType, v, SensorManager.getRotation());
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mSensors & SENSOR_ORIENTATION_RAW)!=0) {
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTarget.onSensorChanged(SENSOR_ORIENTATION_RAW, v);
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mSensors & SENSOR_ORIENTATION)!=0) {
15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    v[0] = mYawfilter.filter(event.timestamp, v[0]);
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTarget.onSensorChanged(SENSOR_ORIENTATION, v);
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTarget.onSensorChanged(legacyType, v);
15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Helper function to convert the specified sensor's data to the windows's
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * coordinate space from the device's coordinate space.
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * output: 3,4,5: values in the old API format
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *         0,1,2: transformed values in the old API format
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private void mapSensorDataToWindow(int sensor,
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float[] values, int orientation) {
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x = values[0];
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float y = values[1];
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float z = values[2];
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (sensor) {
15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ORIENTATION:
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ORIENTATION_RAW:
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    z = -z;
15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ACCELEROMETER:
15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x = -x;
15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y = -y;
15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    z = -z;
15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_MAGNETIC_FIELD:
16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x = -x;
16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y = -y;
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = x;
16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = y;
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = z;
16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[3] = x;
16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[4] = y;
16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[5] = z;
16107895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian
16117895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian            if ((orientation & Surface.ROTATION_90) != 0) {
16127895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                // handles 90 and 270 rotation
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                switch (sensor) {
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ACCELEROMETER:
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_MAGNETIC_FIELD:
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[0] =-y;
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[1] = x;
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[2] = z;
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ORIENTATION:
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ORIENTATION_RAW:
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[0] = x + ((x < 270) ? 90 : -270);
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[1] = z;
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[2] = y;
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16287895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian            if ((orientation & Surface.ROTATION_180) != 0) {
16297895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                x = values[0];
16307895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                y = values[1];
16317895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                z = values[2];
16327895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                // handles 180 (flip) and 270 (flip + 90) rotation
16337895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                switch (sensor) {
16347895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_ACCELEROMETER:
16357895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_MAGNETIC_FIELD:
16367895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[0] =-x;
16377895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[1] =-y;
16387895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[2] = z;
16397895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        break;
16407895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_ORIENTATION:
16417895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_ORIENTATION_RAW:
16427895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[0] = (x >= 180) ? (x - 180) : (x + 180);
16437895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[1] =-y;
16447895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[2] =-z;
16457895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        break;
16467895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                }
16477895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian            }
16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1650287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class LmsFilter {
16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final int SENSORS_RATE_MS = 20;
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final int COUNT = 12;
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final float PREDICTION_RATIO = 1.0f/3.0f;
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final float PREDICTION_TIME = (SENSORS_RATE_MS*COUNT/1000.0f)*PREDICTION_RATIO;
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mV[] = new float[COUNT*2];
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mT[] = new float[COUNT*2];
16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mIndex;
16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public LmsFilter() {
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIndex = COUNT;
16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public float filter(long time, float in) {
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float v = in;
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float ns = 1.0f / 1000000000.0f;
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float t = time*ns;
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float v1 = mV[mIndex];
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((v-v1) > 180) {
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                v -= 360;
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if ((v1-v) > 180) {
16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                v += 360;
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* Manage the circular buffer, we write the data twice spaced
16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * by COUNT values, so that we don't have to copy the array
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * when it's full
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIndex++;
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIndex >= COUNT*2)
16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mIndex = COUNT;
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mV[mIndex] = v;
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mT[mIndex] = t;
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mV[mIndex-COUNT] = v;
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mT[mIndex-COUNT] = t;
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float A, B, C, D, E;
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float a, b;
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int i;
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            A = B = C = D = E = 0;
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (i=0 ; i<COUNT-1 ; i++) {
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int j = mIndex - 1 - i;
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float Z = mV[j];
16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float T = 0.5f*(mT[j] + mT[j+1]) - t;
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float dT = mT[j] - mT[j+1];
16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dT *= dT;
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                A += Z*dT;
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                B += T*(T*dT);
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                C +=   (T*dT);
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                D += Z*(T*dT);
17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                E += dT;
17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            b = (A*B + C*D) / (E*B + C*C);
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            a = (E*b - A) / C;
17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float f = b + PREDICTION_TIME*a;
17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Normalize
17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f *= (1.0f / 360.0f);
17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (((f>=0)?f:-f) >= 0.5f)
17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                f = f - (float)Math.ceil(f + 0.5f) + 1.0f;
17119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (f < 0)
17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                f += 1.0f;
17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f *= 360.0f;
17149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return f;
17159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1718287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian
17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void nativeClassInit();
17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native int sensors_module_init();
17229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native int sensors_module_get_next_sensor(Sensor sensor, int next);
17239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Used within this module from outside SensorManager, don't make private
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static native int sensors_data_init();
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static native int sensors_data_uninit();
1727270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood    static native int sensors_data_open(FileDescriptor[] fds, int[] ints);
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static native int sensors_data_close();
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static native int sensors_data_poll(float[] values, int[] status, long[] timestamp);
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1731