SensorManager.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
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;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ParcelFileDescriptor;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseArray;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IRotationWatcher;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowManager;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Surface;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collections;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Class that lets you access the device's sensors. Get an instance of this
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * class by calling {@link android.content.Context#getSystemService(java.lang.String)
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Context.getSystemService()} with an argument of {@link android.content.Context#SENSOR_SERVICE}.
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SensorManager extends IRotationWatcher.Stub
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "SensorManager";
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final float[] mTempMatrix = new float[16];
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* NOTE: sensor IDs must be a power of 2 */
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A constant describing an orientation sensor.
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * See {@link android.hardware.SensorListener SensorListener} for more details.
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ORIENTATION = 1 << 0;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A constant describing an accelerometer.
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * See {@link android.hardware.SensorListener SensorListener} for more details.
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ACCELEROMETER = 1 << 1;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A constant describing a temperature sensor
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * See {@link android.hardware.SensorListener SensorListener} for more details.
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_TEMPERATURE = 1 << 2;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A constant describing a magnetic sensor
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * See {@link android.hardware.SensorListener SensorListener} for more details.
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MAGNETIC_FIELD = 1 << 3;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A constant describing an ambient light sensor
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * See {@link android.hardware.SensorListener SensorListener} for more details.
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_LIGHT = 1 << 4;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A constant describing a proximity sensor
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * See {@link android.hardware.SensorListener SensorListener} for more details.
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_PROXIMITY = 1 << 5;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A constant describing a Tricorder
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * See {@link android.hardware.SensorListener SensorListener} for more details.
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_TRICORDER = 1 << 6;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A constant describing an orientation sensor.
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * See {@link android.hardware.SensorListener SensorListener} for more details.
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** A constant that includes all sensors */
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ALL = 0x7F;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Smallest sensor ID */
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MIN = SENSOR_ORIENTATION;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Largest sensor ID */
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1);
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Index of the X value in the array returned by
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.SensorListener#onSensorChanged} */
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DATA_X = 0;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Index of the Y value in the array returned by
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.SensorListener#onSensorChanged} */
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DATA_Y = 1;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Index of the Z value in the array returned by
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.SensorListener#onSensorChanged} */
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DATA_Z = 2;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Offset to the untransformed values in the array returned by
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.SensorListener#onSensorChanged} */
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_INDEX = 3;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Index of the untransformed X value in the array returned by
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.SensorListener#onSensorChanged} */
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_X = 3;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Index of the untransformed Y value in the array returned by
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.SensorListener#onSensorChanged} */
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_Y = 4;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Index of the untransformed Z value in the array returned by
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.SensorListener#onSensorChanged} */
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_Z = 5;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Standard gravity (g) on Earth. This value is equivalent to 1G */
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float STANDARD_GRAVITY = 9.80665f;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** values returned by the accelerometer in various locations in the universe.
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * all values are in SI units (m/s^2) */
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_SUN             = 275.0f;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MERCURY         = 3.70f;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_VENUS           = 8.87f;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_EARTH           = 9.80665f;
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MOON            = 1.6f;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MARS            = 3.71f;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_JUPITER         = 23.12f;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_SATURN          = 8.96f;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_URANUS          = 8.69f;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_NEPTUNE         = 11.0f;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_PLUTO           = 0.6f;
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_DEATH_STAR_I    = 0.000000353036145f;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_THE_ISLAND      = 4.815162342f;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Maximum magnetic field on Earth's surface */
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Minimum magnetic field on Earth's surface */
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Various luminance values during the day (lux) */
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNLIGHT     = 110000.0f;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SHADE        = 20000.0f;
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_OVERCAST     = 10000.0f;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNRISE      = 400.0f;
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_CLOUDY       = 100.0f;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Various luminance values during the night (lux) */
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_FULLMOON     = 0.25f;
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_NO_MOON      = 0.001f;
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** get sensor data as fast as possible */
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_FASTEST = 0;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate suitable for games */
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_GAME = 1;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate suitable for the user interface  */
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_UI = 2;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate (default) suitable for screen orientation changes */
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_NORMAL = 3;
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The values returned by this sensor cannot be trusted, calibration
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is needed or the environment doesn't allow readings */
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_UNRELIABLE = 0;
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** This sensor is reporting data with low accuracy, calibration with the
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * environment is needed */
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** This sensor is reporting data with an average level of accuracy,
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * calibration with the environment may improve the readings */
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** This sensor is reporting data with maximum accuracy */
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_X = 1;
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_Y = 2;
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_Z = 3;
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_X = AXIS_X | 0x80;
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_Y = AXIS_Y | 0x80;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_Z = AXIS_Z | 0x80;
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ISensorService mSensorService;
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Looper mMainLooper;
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("deprecation")
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<SensorListener, LegacyListener> mLegacyListenersMap =
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<SensorListener, LegacyListener>();
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int SENSOR_DISABLE = -1;
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean sSensorModuleInitialized = false;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static SparseArray<List<Sensor>> sSensorListByType = new SparseArray<List<Sensor>>();
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static IWindowManager sWindowManager;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int sRotation = Surface.ROTATION_0;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* The thread and the sensor list are global to the process
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * but the actual thread is spawned on demand */
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static SensorThread sSensorThread;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Used within this module from outside SensorManager, don't make private
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final ArrayList<ListenerDelegate> sListeners =
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new ArrayList<ListenerDelegate>();
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static private class SensorThread {
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Thread mThread;
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SensorThread() {
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // this gets to the sensor module. We can have only one per process.
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sensors_data_init();
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected void finalize() {
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sensors_data_uninit();
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // must be called with sListeners lock
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void startLocked(ISensorService service) {
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mThread == null) {
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ParcelFileDescriptor fd = service.getDataChanel();
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mThread = new Thread(new SensorThreadRunnable(fd),
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            SensorThread.class.getName());
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mThread.start();
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "RemoteException in startLocked: ", e);
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private class SensorThreadRunnable implements Runnable {
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            private ParcelFileDescriptor mSensorDataFd;
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorThreadRunnable(ParcelFileDescriptor fd) {
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSensorDataFd = fd;
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public void run() {
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //Log.d(TAG, "entering main sensor thread");
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float[] values = new float[3];
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int[] status = new int[1];
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final long timestamp[] = new long[1];
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mSensorDataFd == null) {
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.e(TAG, "mSensorDataFd == NULL, exiting");
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return;
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // this thread is guaranteed to be unique
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sensors_data_open(mSensorDataFd.getFileDescriptor());
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mSensorDataFd.close();
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (IOException e) {
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // *shrug*
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.e(TAG, "IOException: ", e);
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSensorDataFd = null;
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while (true) {
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // wait for an event
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final int sensor = sensors_data_poll(values, status, timestamp);
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (sensor == -1) {
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // we lost the connection to the event stream. this happens
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // when the last listener is removed.
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.d(TAG, "_sensors_data_poll() failed, we bail out.");
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    int accuracy = status[0];
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (sListeners) {
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (sListeners.isEmpty()) {
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // we have no more listeners, terminate the thread
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            sensors_data_close();
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mThread = null;
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            break;
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        final Sensor sensorObject = sHandleToSensor.get(sensor);
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (sensorObject != null) {
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // report the sensor event to all listeners that
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // care about it.
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            final int size = sListeners.size();
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            for (int i=0 ; i<size ; i++) {
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                ListenerDelegate listener = sListeners.get(i);
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (listener.hasSensor(sensorObject)) {
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    // this is asynchronous (okay to call
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    // with sListeners lock held).
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    listener.onSensorChangedLocked(sensorObject,
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            values, timestamp, accuracy);
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //Log.d(TAG, "exiting main sensor thread");
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*-----------------------------------------------------------------------*/
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class ListenerDelegate extends Binder {
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final SensorEventListener mSensorEventListener;
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final Handler mHandler;
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private SensorEvent mValuesPool;
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int mSensors;
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensorEventListener = listener;
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // currently we create one Handler instance per listener, but we could
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // have one per looper (we'd need to pass the ListenerDelegate
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // instance to handleMessage and keep track of them separately).
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler = new Handler(looper) {
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                @Override
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                public void handleMessage(Message msg) {
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SensorEvent t = (SensorEvent)msg.obj;
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.accuracy >= 0) {
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy);
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mSensorEventListener.onSensorChanged(t);
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    returnToPool(t);
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            };
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            addSensor(sensor);
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected SensorEvent createSensorEvent() {
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // maximal size for all legacy events is 3
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new SensorEvent(3);
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected SensorEvent getFromPool() {
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorEvent t = null;
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // remove the array from the pool
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                t = mValuesPool;
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mValuesPool = null;
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (t == null) {
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // the pool was empty, we need a new one
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                t = createSensorEvent();
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return t;
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected void returnToPool(SensorEvent t) {
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // put back the array into the pool
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mValuesPool == null) {
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mValuesPool = t;
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Object getListener() {
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSensorEventListener;
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int addSensor(Sensor sensor) {
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors |= 1<<sensor.getHandle();
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensorList.add(sensor);
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSensors;
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int removeSensor(Sensor sensor) {
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors &= ~(1<<sensor.getHandle());
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensorList.remove(sensor);
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSensors;
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean hasSensor(Sensor sensor) {
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ((mSensors & (1<<sensor.getHandle())) != 0);
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> getSensors() {
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSensorList;
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void onSensorChangedLocked(Sensor sensor, float[] values, long[] timestamp, int accuracy) {
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorEvent t = getFromPool();
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float[] v = t.values;
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[0] = values[0];
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[1] = values[1];
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[2] = values[2];
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.timestamp = timestamp[0];
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.accuracy = accuracy;
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.sensor = sensor;
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Message msg = Message.obtain();
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            msg.what = 0;
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            msg.obj = t;
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler.sendMessage(msg);
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SensorManager(Looper mainLooper) {
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSensorService = ISensorService.Stub.asInterface(
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ServiceManager.getService(Context.SENSOR_SERVICE));
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMainLooper = mainLooper;
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(sListeners) {
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!sSensorModuleInitialized) {
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sSensorModuleInitialized = true;
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                nativeClassInit();
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sWindowManager = IWindowManager.Stub.asInterface(
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ServiceManager.getService("window"));
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (sWindowManager != null) {
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // if it's null we're running in the system process
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // which won't get the rotated values
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sRotation = sWindowManager.watchRotation(this);
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // initialize the sensor list
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sensors_module_init();
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final ArrayList<Sensor> fullList = sFullSensorsList;
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int i = 0;
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Sensor sensor = new Sensor();
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i = sensors_module_get_next_sensor(sensor, i);
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (i>=0) {
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.d(TAG, "found sensor: " + sensor.getName() +
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                ", handle=" + sensor.getHandle());
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sensor.setLegacyType(getLegacySensorType(sensor.getType()));
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fullList.add(sensor);
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sHandleToSensor.append(sensor.getHandle(), sensor);
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } while (i>0);
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sSensorThread = new SensorThread();
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getLegacySensorType(int type) {
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (type) {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_ACCELEROMETER:
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_ACCELEROMETER;
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_MAGNETIC_FIELD:
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_MAGNETIC_FIELD;
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_ORIENTATION:
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_ORIENTATION_RAW;
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case Sensor.TYPE_TEMPERATURE:
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return SENSOR_TEMPERATURE;
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** @return available sensors.
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link SensorManager#getSensorList(int)} instead
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getSensors() {
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int result = 0;
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ArrayList<Sensor> fullList = sFullSensorsList;
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (Sensor i : fullList) {
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (i.getType()) {
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_ACCELEROMETER:
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_ACCELEROMETER;
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_MAGNETIC_FIELD:
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_MAGNETIC_FIELD;
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_ORIENTATION:
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_ORIENTATION |
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    SensorManager.SENSOR_ORIENTATION_RAW;
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Use this method to get the list of available sensors of a certain
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * type. Make multiple calls to get sensors of different types or use
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the sensors.
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param type of sensors requested
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a list of sensors matching the asked type.
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<Sensor> getSensorList(int type) {
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // cache the returned lists the first time
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> list;
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ArrayList<Sensor> fullList = sFullSensorsList;
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(fullList) {
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            list = sSensorListByType.get(type);
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (list == null) {
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (type == Sensor.TYPE_ALL) {
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    list = fullList;
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    list = new ArrayList<Sensor>();
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (Sensor i : fullList) {
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (i.getType() == type)
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            list.add(i);
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                list = Collections.unmodifiableList(list);
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sSensorListByType.append(type, list);
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return list;
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Use this method to get the default sensor for a given type. Note that
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the returned sensor could be a composite sensor, and its data could be
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * averaged or filtered. If you need to access the raw sensors use
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link SensorManager#getSensorList(int) getSensorList}.
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param type of sensors requested
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the default sensors matching the asked type.
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Sensor getDefaultSensor(int type) {
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: need to be smarter, for now, just return the 1st sensor
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> l = getSensorList(type);
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return l.isEmpty() ? null : l.get(0);
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registers a listener for given sensors.
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead.
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener sensor listener object
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sensors a bit masks of the sensors to register to
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the sensor is supported and successfully enabled
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorListener listener, int sensors) {
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registers a SensorListener for given sensors.
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead.
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener sensor listener object
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sensors a bit masks of the sensors to register to
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rate rate of events. This is only a hint to the system. events
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * may be received faster or slower than the specified rate. Usually events
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * are received faster.
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the sensor is supported and successfully enabled
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorListener listener, int sensors, int rate) {
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result = false;
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("deprecation")
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean registerLegacyListener(int legacyType, int type,
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorListener listener, int sensors, int rate)
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result = false;
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Are we activating this legacy sensor?
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((sensors & legacyType) != 0) {
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // if so, find a suitable Sensor
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Sensor sensor = getDefaultSensor(type);
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sensor != null) {
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If we don't already have one, create a LegacyListener
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // to wrap this listener and process the events as
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // they are expected by legacy apps.
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                LegacyListener legacyListener = null;
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                synchronized (mLegacyListenersMap) {
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    legacyListener = mLegacyListenersMap.get(listener);
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (legacyListener == null) {
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // we didn't find a LegacyListener for this client,
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // create one, and put it in our list.
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        legacyListener = new LegacyListener(listener);
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mLegacyListenersMap.put(listener, legacyListener);
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // register this legacy sensor with this legacy listener
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                legacyListener.registerSensor(legacyType);
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // and finally, register the legacy listener with the new apis
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                result = registerListener(legacyListener, sensor, rate);
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for the sensors with which it is registered.
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link SensorManager#unregisterListener(SensorEventListener, Sensor)}
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead.
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener a SensorListener object
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sensors a bit masks of the sensors to unregister from
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorListener listener, int sensors) {
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("deprecation")
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void unregisterLegacyListener(int legacyType, int type,
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SensorListener listener, int sensors)
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // do we know about this listener?
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LegacyListener legacyListener = null;
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mLegacyListenersMap) {
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            legacyListener = mLegacyListenersMap.get(listener);
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (legacyListener != null) {
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Are we deactivating this legacy sensor?
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((sensors & legacyType) != 0) {
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // if so, find the corresponding Sensor
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Sensor sensor = getDefaultSensor(type);
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (sensor != null) {
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // unregister this legacy sensor and if we don't
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // need the corresponding Sensor, unregister it too
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (legacyListener.unregisterSensor(legacyType)) {
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // corresponding sensor not needed, unregister
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        unregisterListener(legacyListener, sensor);
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // finally check if we still need the legacyListener
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // in our mapping, if not, get rid of it too.
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        synchronized(sListeners) {
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            boolean found = false;
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            for (ListenerDelegate i : sListeners) {
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (i.getListener() == legacyListener) {
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    found = true;
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    break;
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (!found) {
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                synchronized (mLegacyListenersMap) {
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    mLegacyListenersMap.remove(listener);
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for all sensors.
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link SensorManager#unregisterListener(SensorEventListener)}
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead.
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener a SensorListener object
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorListener listener) {
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for the sensors with which it is registered.
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener a SensorEventListener object
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sensor the sensor to unregister from
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorEventListener listener, Sensor sensor) {
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterListener((Object)listener, sensor);
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for all sensors.
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener a SensorListener object
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorEventListener listener) {
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterListener((Object)listener);
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registers a {@link android.hardware.SensorEventListener SensorEventListener}
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for the given sensor.
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object.
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rate The rate {@link android.hardware.SensorEvent sensor events} are delivered at.
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is only a hint to the system. Events may be received faster or
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * slower than the specified rate. Usually events are received faster.
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the sensor is supported and successfully enabled.
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return registerListener(listener, sensor, rate, null);
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registers a {@link android.hardware.SensorEventListener SensorEventListener}
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for the given sensor.
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object.
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rate The rate {@link android.hardware.SensorEvent sensor events} are delivered at.
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is only a hint to the system. Events may be received faster or
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * slower than the specified rate. Usually events are received faster.
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param handler The {@link android.os.Handler Handler} the
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.SensorEvent sensor events} will be delivered to.
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the sensor is supported and successfully enabled.
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Handler handler) {
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null || sensor == null) {
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result;
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int delay = -1;
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (rate) {
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_FASTEST:
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delay = 0;
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_GAME:
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delay = 20;
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_UI:
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delay = 60;
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_NORMAL:
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delay = 200;
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (sListeners) {
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ListenerDelegate l = null;
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (ListenerDelegate i : sListeners) {
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (i.getListener() == listener) {
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        l = i;
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String name = sensor.getName();
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int handle = sensor.getHandle();
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (l == null) {
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    l = new ListenerDelegate(listener, sensor, handler);
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result = mSensorService.enableSensor(l, name, handle, delay);
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (result) {
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sListeners.add(l);
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sListeners.notify();
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!sListeners.isEmpty()) {
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sSensorThread.startLocked(mSensorService);
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result = mSensorService.enableSensor(l, name, handle, delay);
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (result) {
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        l.addSensor(sensor);
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "RemoteException in registerListener: ", e);
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            result = false;
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void unregisterListener(Object listener, Sensor sensor) {
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null || sensor == null) {
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (sListeners) {
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int size = sListeners.size();
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i=0 ; i<size ; i++) {
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ListenerDelegate l = sListeners.get(i);
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (l.getListener() == listener) {
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // disable these sensors
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        String name = sensor.getName();
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int handle = sensor.getHandle();
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // if we have no more sensors enabled on this listener,
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // take it off the list.
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (l.removeSensor(sensor) == 0) {
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            sListeners.remove(i);
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "RemoteException in unregisterListener: ", e);
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void unregisterListener(Object listener) {
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (sListeners) {
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int size = sListeners.size();
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i=0 ; i<size ; i++) {
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ListenerDelegate l = sListeners.get(i);
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (l.getListener() == listener) {
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // disable all sensors for this listener
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        for (Sensor sensor : l.getSensors()) {
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            String name = sensor.getName();
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            int handle = sensor.getHandle();
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sListeners.remove(i);
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "RemoteException in unregisterListener: ", e);
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes the inclination matrix <b>I</b> as well as the rotation
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * matrix <b>R</b> transforming a vector from the
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * device coordinate system to the world's coordinate system which is
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * defined as a direct orthonormal basis, where:
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the ground at the device's current location and roughly points East).</li>
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Y is tangential to the ground at the device's current location and
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * points towards the magnetic North Pole.</li>
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Z points towards the sky and is perpendicular to the ground.</li>
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>By definition:
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>[0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity)
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>[0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b>
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (m = magnitude of geomagnetic field)
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p><b>R</b> is the identity matrix when the device is aligned with the
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * world's coordinate system, that is, when the device's X axis points
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * toward East, the Y axis points to the North Pole and the device is facing
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the sky.
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p><b>I</b> is a rotation matrix transforming the geomagnetic
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * vector into the same coordinate space as gravity (the world's coordinate
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * space). <b>I</b> is a simple rotation around the X axis.
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The inclination angle in radians can be computed with
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getInclination}.
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p> Each matrix is returned either as a 3x3 or 4x4 row-major matrix
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * depending on the length of the passed array:
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p><u>If the array length is 16:</u>
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]   M[ 3]  \
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 4]   M[ 5]   M[ 6]   M[ 7]  |
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 8]   M[ 9]   M[10]   M[11]  |
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \  M[12]   M[13]   M[14]   M[15]  /
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This matrix is ready to be used by OpenGL ES's
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int)
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * glLoadMatrixf(float[], int)}.
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Note that because OpenGL matrices are column-major matrices you must
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * transpose the matrix before using it. However, since the matrix is a
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rotation matrix, its transpose is also its inverse, conveniently, it is
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * often the inverse of the rotation that is needed for rendering; it can
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * therefore be used with OpenGL ES directly.
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Also note that the returned matrices always have this form:
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]   0  \
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 4]   M[ 5]   M[ 6]   0  |
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 8]   M[ 9]   M[10]   0  |
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \      0       0       0   1  /
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p><u>If the array length is 9:</u>
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]  \
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 3]   M[ 4]   M[ 5]  |
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \  M[ 6]   M[ 7]   M[ 8]  /
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The inverse of each matrix can be computed easily by taking its
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * transpose.
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The matrices returned by this function are meaningful only when the
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * device is not free-falling and it is not close to the magnetic north.
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If the device is accelerating, or placed into a strong magnetic field,
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the returned matrices may be inaccurate.
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param R is an array of 9 floats holding the rotation matrix <b>R</b>
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when this function returns. R can be null.<p>
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param I is an array of 9 floats holding the rotation matrix <b>I</b>
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when this function returns. I can be null.<p>
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param gravity is an array of 3 floats containing the gravity vector
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * expressed in the device's coordinate. You can simply use the
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.SensorEvent#values values}
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returned by a {@link android.hardware.SensorEvent SensorEvent} of a
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.Sensor Sensor} of type
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.Sensor#TYPE_ACCELEROMETER TYPE_ACCELEROMETER}.<p>
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param geomagnetic is an array of 3 floats containing the geomagnetic
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * vector expressed in the device's coordinate. You can simply use the
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.SensorEvent#values values}
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returned by a {@link android.hardware.SensorEvent SensorEvent} of a
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.Sensor Sensor} of type
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD TYPE_MAGNETIC_FIELD}.
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   true on success<p>
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   false on failure (for instance, if the device is in free fall).
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   On failure the output matrices are not modified.
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean getRotationMatrix(float[] R, float[] I,
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] gravity, float[] geomagnetic) {
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: move this to native code for efficiency
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Ax = gravity[0];
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Ay = gravity[1];
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Az = gravity[2];
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ex = geomagnetic[0];
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ey = geomagnetic[1];
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ez = geomagnetic[2];
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hx = Ey*Az - Ez*Ay;
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hy = Ez*Ax - Ex*Az;
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hz = Ex*Ay - Ey*Ax;
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (normH < 0.1f) {
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // device is close to free fall (or in space?), or close to
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // magnetic north pole. Typical values are  > 100.
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float invH = 1.0f / normH;
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hx *= invH;
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hy *= invH;
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hz *= invH;
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Ax *= invA;
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Ay *= invA;
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Az *= invA;
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Mx = Ay*Hz - Az*Hy;
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float My = Az*Hx - Ax*Hz;
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Mz = Ax*Hy - Ay*Hx;
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (R != null) {
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (R.length == 9) {
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[0] = Hx;     R[1] = Hy;     R[2] = Hz;
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[3] = Mx;     R[4] = My;     R[5] = Mz;
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[6] = Ax;     R[7] = Ay;     R[8] = Az;
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (R.length == 16) {
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[0]  = Hx;    R[1]  = Hy;    R[2]  = Hz;   R[3]  = 0;
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[4]  = Mx;    R[5]  = My;    R[6]  = Mz;   R[7]  = 0;
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[8]  = Ax;    R[9]  = Ay;    R[10] = Az;   R[11] = 0;
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[12] = 0;     R[13] = 0;     R[14] = 0;    R[15] = 1;
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (I != null) {
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // compute the inclination matrix by projecting the geomagnetic
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // vector onto the Z (gravity) and X (horizontal component
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // of geomagnetic vector) axes.
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (I.length == 9) {
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[0] = 1;     I[1] = 0;     I[2] = 0;
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[3] = 0;     I[4] = c;     I[5] = s;
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[6] = 0;     I[7] =-s;     I[8] = c;
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (I.length == 16) {
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[0] = 1;     I[1] = 0;     I[2] = 0;
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[4] = 0;     I[5] = c;     I[6] = s;
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[8] = 0;     I[9] =-s;     I[10]= c;
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[15] = 1;
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes the geomagnetic inclination angle in radians from the
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}.
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param I inclination matrix see {@link #getRotationMatrix}.
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The geomagnetic inclination angle in radians.
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static float getInclination(float[] I) {
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (I.length == 9) {
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (float)Math.atan2(I[5], I[4]);
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (float)Math.atan2(I[6], I[5]);
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rotates the supplied rotation matrix so it is expressed in a
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * different coordinate system. This is typically used when an application
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * needs to compute the three orientation angles of the device (see
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getOrientation}) in a different coordinate system.
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>When the rotation matrix is used for drawing (for instance with
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * OpenGL ES), it usually <b>doesn't need</b> to be transformed by this
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * function, unless the screen is physically rotated, such as when used
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in landscape mode.
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p><u>Examples:</u><p>
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Using the camera (Y axis along the camera's axis) for an augmented
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * reality application where the rotation angles are needed :</li><p>
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code><p>
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Using the device as a mechanical compass in landscape mode:</li><p>
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code><p>
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Beware of the above example. This call is needed only if the device is
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * physically used in landscape mode to calculate the rotation angles (see
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getOrientation}).
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If the rotation matrix is also used for rendering, it may not need to
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be transformed, for instance if your {@link android.app.Activity
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Activity} is running in landscape mode.
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Since the resulting coordinate system is orthonormal, only two axes
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * need to be specified.
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param inR the rotation matrix to be transformed. Usually it is the
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * matrix returned by {@link #getRotationMatrix}.
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param X defines on which world axis and direction the X axis of the
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        device is mapped.
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param Y defines on which world axis and direction the Y axis of the
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        device is mapped.
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param outR the transformed rotation matrix. inR and outR can be the same
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        array, but it is not recommended for performance reason.
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true on success. false if the input parameters are incorrect, for
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instance if X and Y define the same axis. Or if inR and outR don't have
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the same length.
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean remapCoordinateSystem(float[] inR, int X, int Y,
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] outR)
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (inR == outR) {
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float[] temp = mTempMatrix;
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(temp) {
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // we don't expect to have a lot of contention
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final int size = outR.length;
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (int i=0 ; i<size ; i++)
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        outR[i] = temp[i];
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return true;
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return remapCoordinateSystemImpl(inR, X, Y, outR);
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y,
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] outR)
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * X and Y define a rotation matrix 'r':
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *                              r[0] ^ r[1]
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * where the 3rd line is the vector product of the first 2 lines
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int length = outR.length;
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (inR.length != length)
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // invalid parameter
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((X & 0x7C)!=0 || (Y & 0x7C)!=0)
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // invalid parameter
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (((X & 0x3)==0) || ((Y & 0x3)==0))
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // no axis specified
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((X & 0x3) == (Y & 0x3))
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // same axis specified
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // this can be calculated by exclusive-or'ing X and Y; except for
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the sign inversion (+/-) which is calculated below.
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int Z = X ^ Y;
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // extract the axis (remove the sign), offset in the range 0 to 2.
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int x = (X & 0x3)-1;
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int y = (Y & 0x3)-1;
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int z = (Z & 0x3)-1;
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // compute the sign of Z (whether it needs to be inverted)
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int axis_y = (z+1)%3;
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int axis_z = (z+2)%3;
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (((x^axis_y)|(y^axis_z)) != 0)
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Z ^= 0x80;
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sx = (X>=0x80);
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sy = (Y>=0x80);
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sz = (Z>=0x80);
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Perform R * r, in avoiding actual muls and adds.
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int rowLength = ((length==16)?4:3);
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int j=0 ; j<3 ; j++) {
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int offset = j*rowLength;
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0 ; i<3 ; i++) {
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (x==i)   outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0];
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (y==i)   outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1];
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (z==i)   outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2];
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (length == 16) {
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            outR[15] = 1;
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes the device's orientation based on the rotation matrix.
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p> When it returns, the array values is filled with the result:
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[0]: <i>azimuth</i>, rotation around the Z axis.</li>
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[1]: <i>pitch</i>, rotation around the X axis.</li>
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li>
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param R rotation matrix see {@link #getRotationMatrix}.
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param values an array of 3 floats to hold the result.
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The array values passed as argument.
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static float[] getOrientation(float[] R, float values[]) {
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * 4x4 (length=16) case:
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   /  R[ 0]   R[ 1]   R[ 2]   0  \
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 4]   R[ 5]   R[ 6]   0  |
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 8]   R[ 9]   R[10]   0  |
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   \      0       0       0   1  /
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * 3x3 (length=9) case:
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   /  R[ 0]   R[ 1]   R[ 2]  \
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 3]   R[ 4]   R[ 5]  |
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   \  R[ 6]   R[ 7]   R[ 8]  /
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (R.length == 9) {
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = (float)Math.atan2(R[1], R[4]);
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = (float)Math.asin(-R[7]);
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = (float)Math.atan2(-R[6], R[8]);
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = (float)Math.atan2(R[1], R[5]);
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = (float)Math.asin(-R[9]);
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = (float)Math.atan2(-R[8], R[10]);
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return values;
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onRotationChanged(int rotation) {
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(sListeners) {
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sRotation  = rotation;
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static int getRotation() {
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(sListeners) {
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return sRotation;
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class LegacyListener implements SensorEventListener {
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mValues[] = new float[6];
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private SensorListener mTarget;
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mSensors;
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final LmsFilter mYawfilter = new LmsFilter();
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LegacyListener(SensorListener target) {
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTarget = target;
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors = 0;
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void registerSensor(int legacyType) {
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors |= legacyType;
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean unregisterSensor(int legacyType) {
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors &= ~legacyType;
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mask = SENSOR_ORIENTATION|SENSOR_ORIENTATION_RAW;
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (((legacyType&mask)!=0) && ((mSensors&mask)!=0)) {
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onAccuracyChanged(Sensor sensor, int accuracy) {
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTarget.onAccuracyChanged(sensor.getLegacyType(), accuracy);
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (AbstractMethodError e) {
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // old app that doesn't implement this method
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // just ignore it.
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onSensorChanged(SensorEvent event) {
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float v[] = mValues;
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[0] = event.values[0];
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[1] = event.values[1];
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[2] = event.values[2];
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int legacyType = event.sensor.getLegacyType();
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mapSensorDataToWindow(legacyType, v, SensorManager.getRotation());
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mSensors & SENSOR_ORIENTATION_RAW)!=0) {
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTarget.onSensorChanged(SENSOR_ORIENTATION_RAW, v);
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mSensors & SENSOR_ORIENTATION)!=0) {
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    v[0] = mYawfilter.filter(event.timestamp, v[0]);
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTarget.onSensorChanged(SENSOR_ORIENTATION, v);
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTarget.onSensorChanged(legacyType, v);
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Helper function to convert the specified sensor's data to the windows's
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * coordinate space from the device's coordinate space.
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * output: 3,4,5: values in the old API format
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *         0,1,2: transformed values in the old API format
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private void mapSensorDataToWindow(int sensor,
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float[] values, int orientation) {
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x = values[0];
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float y = values[1];
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float z = values[2];
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (sensor) {
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ORIENTATION:
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ORIENTATION_RAW:
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    z = -z;
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ACCELEROMETER:
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x = -x;
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y = -y;
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    z = -z;
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_MAGNETIC_FIELD:
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x = -x;
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y = -y;
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = x;
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = y;
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = z;
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[3] = x;
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[4] = y;
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[5] = z;
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // TODO: add support for 180 and 270 orientations
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (orientation == Surface.ROTATION_90) {
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                switch (sensor) {
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ACCELEROMETER:
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_MAGNETIC_FIELD:
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[0] =-y;
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[1] = x;
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[2] = z;
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ORIENTATION:
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ORIENTATION_RAW:
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[0] = x + ((x < 270) ? 90 : -270);
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[1] = z;
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[2] = y;
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class LmsFilter {
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final int SENSORS_RATE_MS = 20;
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final int COUNT = 12;
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final float PREDICTION_RATIO = 1.0f/3.0f;
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final float PREDICTION_TIME = (SENSORS_RATE_MS*COUNT/1000.0f)*PREDICTION_RATIO;
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mV[] = new float[COUNT*2];
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mT[] = new float[COUNT*2];
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mIndex;
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public LmsFilter() {
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIndex = COUNT;
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public float filter(long time, float in) {
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float v = in;
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float ns = 1.0f / 1000000000.0f;
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float t = time*ns;
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float v1 = mV[mIndex];
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((v-v1) > 180) {
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                v -= 360;
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if ((v1-v) > 180) {
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                v += 360;
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* Manage the circular buffer, we write the data twice spaced
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * by COUNT values, so that we don't have to copy the array
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * when it's full
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIndex++;
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIndex >= COUNT*2)
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mIndex = COUNT;
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mV[mIndex] = v;
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mT[mIndex] = t;
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mV[mIndex-COUNT] = v;
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mT[mIndex-COUNT] = t;
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float A, B, C, D, E;
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float a, b;
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int i;
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            A = B = C = D = E = 0;
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (i=0 ; i<COUNT-1 ; i++) {
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int j = mIndex - 1 - i;
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float Z = mV[j];
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float T = 0.5f*(mT[j] + mT[j+1]) - t;
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float dT = mT[j] - mT[j+1];
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dT *= dT;
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                A += Z*dT;
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                B += T*(T*dT);
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                C +=   (T*dT);
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                D += Z*(T*dT);
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                E += dT;
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            b = (A*B + C*D) / (E*B + C*C);
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            a = (E*b - A) / C;
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float f = b + PREDICTION_TIME*a;
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Normalize
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f *= (1.0f / 360.0f);
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (((f>=0)?f:-f) >= 0.5f)
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                f = f - (float)Math.ceil(f + 0.5f) + 1.0f;
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (f < 0)
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                f += 1.0f;
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f *= 360.0f;
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return f;
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void nativeClassInit();
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native int sensors_module_init();
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native int sensors_module_get_next_sensor(Sensor sensor, int next);
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Used within this module from outside SensorManager, don't make private
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static native int sensors_data_init();
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static native int sensors_data_uninit();
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static native int sensors_data_open(FileDescriptor fd);
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static native int sensors_data_close();
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static native int sensors_data_poll(float[] values, int[] status, long[] timestamp);
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1463