Home | History | Annotate | Download | only in hardware
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.hardware;
     18 
     19 import android.os.Looper;
     20 import android.os.Process;
     21 import android.os.RemoteException;
     22 import android.os.Handler;
     23 import android.os.Message;
     24 import android.os.ServiceManager;
     25 import android.util.Log;
     26 import android.util.SparseArray;
     27 import android.util.SparseBooleanArray;
     28 import android.util.SparseIntArray;
     29 import android.view.IRotationWatcher;
     30 import android.view.IWindowManager;
     31 import android.view.Surface;
     32 
     33 import java.util.ArrayList;
     34 import java.util.Collections;
     35 import java.util.HashMap;
     36 import java.util.List;
     37 
     38 /**
     39  * <p>
     40  * SensorManager lets you access the device's {@link android.hardware.Sensor
     41  * sensors}. Get an instance of this class by calling
     42  * {@link android.content.Context#getSystemService(java.lang.String)
     43  * Context.getSystemService()} with the argument
     44  * {@link android.content.Context#SENSOR_SERVICE}.
     45  * </p>
     46  * <p>
     47  * Always make sure to disable sensors you don't need, especially when your
     48  * activity is paused. Failing to do so can drain the battery in just a few
     49  * hours. Note that the system will <i>not</i> disable sensors automatically when
     50  * the screen turns off.
     51  * </p>
     52  *
     53  * <pre class="prettyprint">
     54  * public class SensorActivity extends Activity, implements SensorEventListener {
     55  *     private final SensorManager mSensorManager;
     56  *     private final Sensor mAccelerometer;
     57  *
     58  *     public SensorActivity() {
     59  *         mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
     60  *         mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
     61  *     }
     62  *
     63  *     protected void onResume() {
     64  *         super.onResume();
     65  *         mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
     66  *     }
     67  *
     68  *     protected void onPause() {
     69  *         super.onPause();
     70  *         mSensorManager.unregisterListener(this);
     71  *     }
     72  *
     73  *     public void onAccuracyChanged(Sensor sensor, int accuracy) {
     74  *     }
     75  *
     76  *     public void onSensorChanged(SensorEvent event) {
     77  *     }
     78  * }
     79  * </pre>
     80  *
     81  * @see SensorEventListener
     82  * @see SensorEvent
     83  * @see Sensor
     84  *
     85  */
     86 public class SensorManager
     87 {
     88     private static final String TAG = "SensorManager";
     89     private static final float[] mTempMatrix = new float[16];
     90 
     91     /* NOTE: sensor IDs must be a power of 2 */
     92 
     93     /**
     94      * A constant describing an orientation sensor. See
     95      * {@link android.hardware.SensorListener SensorListener} for more details.
     96      *
     97      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
     98      */
     99     @Deprecated
    100     public static final int SENSOR_ORIENTATION = 1 << 0;
    101 
    102     /**
    103      * A constant describing an accelerometer. See
    104      * {@link android.hardware.SensorListener SensorListener} for more details.
    105      *
    106      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    107      */
    108     @Deprecated
    109     public static final int SENSOR_ACCELEROMETER = 1 << 1;
    110 
    111     /**
    112      * A constant describing a temperature sensor See
    113      * {@link android.hardware.SensorListener SensorListener} for more details.
    114      *
    115      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    116      */
    117     @Deprecated
    118     public static final int SENSOR_TEMPERATURE = 1 << 2;
    119 
    120     /**
    121      * A constant describing a magnetic sensor See
    122      * {@link android.hardware.SensorListener SensorListener} for more details.
    123      *
    124      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    125      */
    126     @Deprecated
    127     public static final int SENSOR_MAGNETIC_FIELD = 1 << 3;
    128 
    129     /**
    130      * A constant describing an ambient light sensor See
    131      * {@link android.hardware.SensorListener SensorListener} for more details.
    132      *
    133      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    134      */
    135     @Deprecated
    136     public static final int SENSOR_LIGHT = 1 << 4;
    137 
    138     /**
    139      * A constant describing a proximity sensor See
    140      * {@link android.hardware.SensorListener SensorListener} for more details.
    141      *
    142      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    143      */
    144     @Deprecated
    145     public static final int SENSOR_PROXIMITY = 1 << 5;
    146 
    147     /**
    148      * A constant describing a Tricorder See
    149      * {@link android.hardware.SensorListener SensorListener} for more details.
    150      *
    151      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    152      */
    153     @Deprecated
    154     public static final int SENSOR_TRICORDER = 1 << 6;
    155 
    156     /**
    157      * A constant describing an orientation sensor. See
    158      * {@link android.hardware.SensorListener SensorListener} for more details.
    159      *
    160      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    161      */
    162     @Deprecated
    163     public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
    164 
    165     /**
    166      * A constant that includes all sensors
    167      *
    168      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    169      */
    170     @Deprecated
    171     public static final int SENSOR_ALL = 0x7F;
    172 
    173     /**
    174      * Smallest sensor ID
    175      *
    176      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    177      */
    178     @Deprecated
    179     public static final int SENSOR_MIN = SENSOR_ORIENTATION;
    180 
    181     /**
    182      * Largest sensor ID
    183      *
    184      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    185      */
    186     @Deprecated
    187     public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1);
    188 
    189 
    190     /**
    191      * Index of the X value in the array returned by
    192      * {@link android.hardware.SensorListener#onSensorChanged}
    193      *
    194      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    195      */
    196     @Deprecated
    197     public static final int DATA_X = 0;
    198 
    199     /**
    200      * Index of the Y value in the array returned by
    201      * {@link android.hardware.SensorListener#onSensorChanged}
    202      *
    203      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    204      */
    205     @Deprecated
    206     public static final int DATA_Y = 1;
    207 
    208     /**
    209      * Index of the Z value in the array returned by
    210      * {@link android.hardware.SensorListener#onSensorChanged}
    211      *
    212      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    213      */
    214     @Deprecated
    215     public static final int DATA_Z = 2;
    216 
    217     /**
    218      * Offset to the untransformed values in the array returned by
    219      * {@link android.hardware.SensorListener#onSensorChanged}
    220      *
    221      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    222      */
    223     @Deprecated
    224     public static final int RAW_DATA_INDEX = 3;
    225 
    226     /**
    227      * Index of the untransformed X value in the array returned by
    228      * {@link android.hardware.SensorListener#onSensorChanged}
    229      *
    230      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    231      */
    232     @Deprecated
    233     public static final int RAW_DATA_X = 3;
    234 
    235     /**
    236      * Index of the untransformed Y value in the array returned by
    237      * {@link android.hardware.SensorListener#onSensorChanged}
    238      *
    239      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    240      */
    241     @Deprecated
    242     public static final int RAW_DATA_Y = 4;
    243 
    244     /**
    245      * Index of the untransformed Z value in the array returned by
    246      * {@link android.hardware.SensorListener#onSensorChanged}
    247      *
    248      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    249      */
    250     @Deprecated
    251     public static final int RAW_DATA_Z = 5;
    252 
    253     /** Standard gravity (g) on Earth. This value is equivalent to 1G */
    254     public static final float STANDARD_GRAVITY = 9.80665f;
    255 
    256     /** Sun's gravity in SI units (m/s^2) */
    257     public static final float GRAVITY_SUN             = 275.0f;
    258     /** Mercury's gravity in SI units (m/s^2) */
    259     public static final float GRAVITY_MERCURY         = 3.70f;
    260     /** Venus' gravity in SI units (m/s^2) */
    261     public static final float GRAVITY_VENUS           = 8.87f;
    262     /** Earth's gravity in SI units (m/s^2) */
    263     public static final float GRAVITY_EARTH           = 9.80665f;
    264     /** The Moon's gravity in SI units (m/s^2) */
    265     public static final float GRAVITY_MOON            = 1.6f;
    266     /** Mars' gravity in SI units (m/s^2) */
    267     public static final float GRAVITY_MARS            = 3.71f;
    268     /** Jupiter's gravity in SI units (m/s^2) */
    269     public static final float GRAVITY_JUPITER         = 23.12f;
    270     /** Saturn's gravity in SI units (m/s^2) */
    271     public static final float GRAVITY_SATURN          = 8.96f;
    272     /** Uranus' gravity in SI units (m/s^2) */
    273     public static final float GRAVITY_URANUS          = 8.69f;
    274     /** Neptune's gravity in SI units (m/s^2) */
    275     public static final float GRAVITY_NEPTUNE         = 11.0f;
    276     /** Pluto's gravity in SI units (m/s^2) */
    277     public static final float GRAVITY_PLUTO           = 0.6f;
    278     /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */
    279     public static final float GRAVITY_DEATH_STAR_I    = 0.000000353036145f;
    280     /** Gravity on the island */
    281     public static final float GRAVITY_THE_ISLAND      = 4.815162342f;
    282 
    283 
    284     /** Maximum magnetic field on Earth's surface */
    285     public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f;
    286     /** Minimum magnetic field on Earth's surface */
    287     public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;
    288 
    289 
    290     /** Standard atmosphere, or average sea-level pressure in hPa (millibar) */
    291     public static final float PRESSURE_STANDARD_ATMOSPHERE = 1013.25f;
    292 
    293 
    294     /** Maximum luminance of sunlight in lux */
    295     public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
    296     /** luminance of sunlight in lux */
    297     public static final float LIGHT_SUNLIGHT     = 110000.0f;
    298     /** luminance in shade in lux */
    299     public static final float LIGHT_SHADE        = 20000.0f;
    300     /** luminance under an overcast sky in lux */
    301     public static final float LIGHT_OVERCAST     = 10000.0f;
    302     /** luminance at sunrise in lux */
    303     public static final float LIGHT_SUNRISE      = 400.0f;
    304     /** luminance under a cloudy sky in lux */
    305     public static final float LIGHT_CLOUDY       = 100.0f;
    306     /** luminance at night with full moon in lux */
    307     public static final float LIGHT_FULLMOON     = 0.25f;
    308     /** luminance at night with no moon in lux*/
    309     public static final float LIGHT_NO_MOON      = 0.001f;
    310 
    311 
    312     /** get sensor data as fast as possible */
    313     public static final int SENSOR_DELAY_FASTEST = 0;
    314     /** rate suitable for games */
    315     public static final int SENSOR_DELAY_GAME = 1;
    316     /** rate suitable for the user interface  */
    317     public static final int SENSOR_DELAY_UI = 2;
    318     /** rate (default) suitable for screen orientation changes */
    319     public static final int SENSOR_DELAY_NORMAL = 3;
    320 
    321 
    322     /**
    323      * The values returned by this sensor cannot be trusted, calibration is
    324      * needed or the environment doesn't allow readings
    325      */
    326     public static final int SENSOR_STATUS_UNRELIABLE = 0;
    327 
    328     /**
    329      * This sensor is reporting data with low accuracy, calibration with the
    330      * environment is needed
    331      */
    332     public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
    333 
    334     /**
    335      * This sensor is reporting data with an average level of accuracy,
    336      * calibration with the environment may improve the readings
    337      */
    338     public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;
    339 
    340     /** This sensor is reporting data with maximum accuracy */
    341     public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;
    342 
    343     /** see {@link #remapCoordinateSystem} */
    344     public static final int AXIS_X = 1;
    345     /** see {@link #remapCoordinateSystem} */
    346     public static final int AXIS_Y = 2;
    347     /** see {@link #remapCoordinateSystem} */
    348     public static final int AXIS_Z = 3;
    349     /** see {@link #remapCoordinateSystem} */
    350     public static final int AXIS_MINUS_X = AXIS_X | 0x80;
    351     /** see {@link #remapCoordinateSystem} */
    352     public static final int AXIS_MINUS_Y = AXIS_Y | 0x80;
    353     /** see {@link #remapCoordinateSystem} */
    354     public static final int AXIS_MINUS_Z = AXIS_Z | 0x80;
    355 
    356     /*-----------------------------------------------------------------------*/
    357 
    358     Looper mMainLooper;
    359     @SuppressWarnings("deprecation")
    360     private HashMap<SensorListener, LegacyListener> mLegacyListenersMap =
    361         new HashMap<SensorListener, LegacyListener>();
    362 
    363     /*-----------------------------------------------------------------------*/
    364 
    365     private static final int SENSOR_DISABLE = -1;
    366     private static boolean sSensorModuleInitialized = false;
    367     private static ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
    368     private static SparseArray<List<Sensor>> sSensorListByType = new SparseArray<List<Sensor>>();
    369     private static IWindowManager sWindowManager;
    370     private static int sRotation = Surface.ROTATION_0;
    371     /* The thread and the sensor list are global to the process
    372      * but the actual thread is spawned on demand */
    373     private static SensorThread sSensorThread;
    374     private static int sQueue;
    375 
    376     // Used within this module from outside SensorManager, don't make private
    377     static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
    378     static final ArrayList<ListenerDelegate> sListeners =
    379         new ArrayList<ListenerDelegate>();
    380 
    381     /*-----------------------------------------------------------------------*/
    382 
    383     private class SensorEventPool {
    384         private final int mPoolSize;
    385         private final SensorEvent mPool[];
    386         private int mNumItemsInPool;
    387 
    388         private SensorEvent createSensorEvent() {
    389             // maximal size for all legacy events is 3
    390             return new SensorEvent(3);
    391         }
    392 
    393         SensorEventPool(int poolSize) {
    394             mPoolSize = poolSize;
    395             mNumItemsInPool = poolSize;
    396             mPool = new SensorEvent[poolSize];
    397         }
    398 
    399         SensorEvent getFromPool() {
    400             SensorEvent t = null;
    401             synchronized (this) {
    402                 if (mNumItemsInPool > 0) {
    403                     // remove the "top" item from the pool
    404                     final int index = mPoolSize - mNumItemsInPool;
    405                     t = mPool[index];
    406                     mPool[index] = null;
    407                     mNumItemsInPool--;
    408                 }
    409             }
    410             if (t == null) {
    411                 // the pool was empty or this item was removed from the pool for
    412                 // the first time. In any case, we need to create a new item.
    413                 t = createSensorEvent();
    414             }
    415             return t;
    416         }
    417 
    418         void returnToPool(SensorEvent t) {
    419             synchronized (this) {
    420                 // is there space left in the pool?
    421                 if (mNumItemsInPool < mPoolSize) {
    422                     // if so, return the item to the pool
    423                     mNumItemsInPool++;
    424                     final int index = mPoolSize - mNumItemsInPool;
    425                     mPool[index] = t;
    426                 }
    427             }
    428         }
    429     }
    430 
    431     private static SensorEventPool sPool;
    432 
    433     /*-----------------------------------------------------------------------*/
    434 
    435     static private class SensorThread {
    436 
    437         Thread mThread;
    438         boolean mSensorsReady;
    439 
    440         SensorThread() {
    441         }
    442 
    443         @Override
    444         protected void finalize() {
    445         }
    446 
    447         // must be called with sListeners lock
    448         boolean startLocked() {
    449             try {
    450                 if (mThread == null) {
    451                     mSensorsReady = false;
    452                     SensorThreadRunnable runnable = new SensorThreadRunnable();
    453                     Thread thread = new Thread(runnable, SensorThread.class.getName());
    454                     thread.start();
    455                     synchronized (runnable) {
    456                         while (mSensorsReady == false) {
    457                             runnable.wait();
    458                         }
    459                     }
    460                     mThread = thread;
    461                 }
    462             } catch (InterruptedException e) {
    463             }
    464             return mThread == null ? false : true;
    465         }
    466 
    467         private class SensorThreadRunnable implements Runnable {
    468             SensorThreadRunnable() {
    469             }
    470 
    471             private boolean open() {
    472                 // NOTE: this cannot synchronize on sListeners, since
    473                 // it's held in the main thread at least until we
    474                 // return from here.
    475                 sQueue = sensors_create_queue();
    476                 return true;
    477             }
    478 
    479             public void run() {
    480                 //Log.d(TAG, "entering main sensor thread");
    481                 final float[] values = new float[3];
    482                 final int[] status = new int[1];
    483                 final long timestamp[] = new long[1];
    484                 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
    485 
    486                 if (!open()) {
    487                     return;
    488                 }
    489 
    490                 synchronized (this) {
    491                     // we've open the driver, we're ready to open the sensors
    492                     mSensorsReady = true;
    493                     this.notify();
    494                 }
    495 
    496                 while (true) {
    497                     // wait for an event
    498                     final int sensor = sensors_data_poll(sQueue, values, status, timestamp);
    499 
    500                     int accuracy = status[0];
    501                     synchronized (sListeners) {
    502                         if (sensor == -1 || sListeners.isEmpty()) {
    503                             // we lost the connection to the event stream. this happens
    504                             // when the last listener is removed or if there is an error
    505                             if (sensor == -1 && !sListeners.isEmpty()) {
    506                                 // log a warning in case of abnormal termination
    507                                 Log.e(TAG, "_sensors_data_poll() failed, we bail out: sensors=" + sensor);
    508                             }
    509                             // we have no more listeners or polling failed, terminate the thread
    510                             sensors_destroy_queue(sQueue);
    511                             sQueue = 0;
    512                             mThread = null;
    513                             break;
    514                         }
    515                         final Sensor sensorObject = sHandleToSensor.get(sensor);
    516                         if (sensorObject != null) {
    517                             // report the sensor event to all listeners that
    518                             // care about it.
    519                             final int size = sListeners.size();
    520                             for (int i=0 ; i<size ; i++) {
    521                                 ListenerDelegate listener = sListeners.get(i);
    522                                 if (listener.hasSensor(sensorObject)) {
    523                                     // this is asynchronous (okay to call
    524                                     // with sListeners lock held).
    525                                     listener.onSensorChangedLocked(sensorObject,
    526                                             values, timestamp, accuracy);
    527                                 }
    528                             }
    529                         }
    530                     }
    531                 }
    532                 //Log.d(TAG, "exiting main sensor thread");
    533             }
    534         }
    535     }
    536 
    537     /*-----------------------------------------------------------------------*/
    538 
    539     private class ListenerDelegate {
    540         private final SensorEventListener mSensorEventListener;
    541         private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
    542         private final Handler mHandler;
    543         public SparseBooleanArray mSensors = new SparseBooleanArray();
    544         public SparseBooleanArray mFirstEvent = new SparseBooleanArray();
    545         public SparseIntArray mSensorAccuracies = new SparseIntArray();
    546 
    547         ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) {
    548             mSensorEventListener = listener;
    549             Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
    550             // currently we create one Handler instance per listener, but we could
    551             // have one per looper (we'd need to pass the ListenerDelegate
    552             // instance to handleMessage and keep track of them separately).
    553             mHandler = new Handler(looper) {
    554                 @Override
    555                 public void handleMessage(Message msg) {
    556                     final SensorEvent t = (SensorEvent)msg.obj;
    557                     final int handle = t.sensor.getHandle();
    558 
    559                     switch (t.sensor.getType()) {
    560                         // Only report accuracy for sensors that support it.
    561                         case Sensor.TYPE_MAGNETIC_FIELD:
    562                         case Sensor.TYPE_ORIENTATION:
    563                             // call onAccuracyChanged() only if the value changes
    564                             final int accuracy = mSensorAccuracies.get(handle);
    565                             if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
    566                                 mSensorAccuracies.put(handle, t.accuracy);
    567                                 mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy);
    568                             }
    569                             break;
    570                         default:
    571                             // For other sensors, just report the accuracy once
    572                             if (mFirstEvent.get(handle) == false) {
    573                                 mFirstEvent.put(handle, true);
    574                                 mSensorEventListener.onAccuracyChanged(
    575                                         t.sensor, SENSOR_STATUS_ACCURACY_HIGH);
    576                             }
    577                             break;
    578                     }
    579 
    580                     mSensorEventListener.onSensorChanged(t);
    581                     sPool.returnToPool(t);
    582                 }
    583             };
    584             addSensor(sensor);
    585         }
    586 
    587         Object getListener() {
    588             return mSensorEventListener;
    589         }
    590 
    591         void addSensor(Sensor sensor) {
    592             mSensors.put(sensor.getHandle(), true);
    593             mSensorList.add(sensor);
    594         }
    595         int removeSensor(Sensor sensor) {
    596             mSensors.delete(sensor.getHandle());
    597             mSensorList.remove(sensor);
    598             return mSensors.size();
    599         }
    600         boolean hasSensor(Sensor sensor) {
    601             return mSensors.get(sensor.getHandle());
    602         }
    603         List<Sensor> getSensors() {
    604             return mSensorList;
    605         }
    606 
    607         void onSensorChangedLocked(Sensor sensor, float[] values, long[] timestamp, int accuracy) {
    608             SensorEvent t = sPool.getFromPool();
    609             final float[] v = t.values;
    610             v[0] = values[0];
    611             v[1] = values[1];
    612             v[2] = values[2];
    613             t.timestamp = timestamp[0];
    614             t.accuracy = accuracy;
    615             t.sensor = sensor;
    616             Message msg = Message.obtain();
    617             msg.what = 0;
    618             msg.obj = t;
    619             mHandler.sendMessage(msg);
    620         }
    621     }
    622 
    623     /**
    624      * {@hide}
    625      */
    626     public SensorManager(Looper mainLooper) {
    627         mMainLooper = mainLooper;
    628 
    629 
    630         synchronized(sListeners) {
    631             if (!sSensorModuleInitialized) {
    632                 sSensorModuleInitialized = true;
    633 
    634                 nativeClassInit();
    635 
    636                 sWindowManager = IWindowManager.Stub.asInterface(
    637                         ServiceManager.getService("window"));
    638                 if (sWindowManager != null) {
    639                     // if it's null we're running in the system process
    640                     // which won't get the rotated values
    641                     try {
    642                         sRotation = sWindowManager.watchRotation(
    643                                 new IRotationWatcher.Stub() {
    644                                     public void onRotationChanged(int rotation) {
    645                                         SensorManager.this.onRotationChanged(rotation);
    646                                     }
    647                                 }
    648                         );
    649                     } catch (RemoteException e) {
    650                     }
    651                 }
    652 
    653                 // initialize the sensor list
    654                 sensors_module_init();
    655                 final ArrayList<Sensor> fullList = sFullSensorsList;
    656                 int i = 0;
    657                 do {
    658                     Sensor sensor = new Sensor();
    659                     i = sensors_module_get_next_sensor(sensor, i);
    660 
    661                     if (i>=0) {
    662                         //Log.d(TAG, "found sensor: " + sensor.getName() +
    663                         //        ", handle=" + sensor.getHandle());
    664                         sensor.setLegacyType(getLegacySensorType(sensor.getType()));
    665                         fullList.add(sensor);
    666                         sHandleToSensor.append(sensor.getHandle(), sensor);
    667                     }
    668                 } while (i>0);
    669 
    670                 sPool = new SensorEventPool( sFullSensorsList.size()*2 );
    671                 sSensorThread = new SensorThread();
    672             }
    673         }
    674     }
    675 
    676     private int getLegacySensorType(int type) {
    677         switch (type) {
    678             case Sensor.TYPE_ACCELEROMETER:
    679                 return SENSOR_ACCELEROMETER;
    680             case Sensor.TYPE_MAGNETIC_FIELD:
    681                 return SENSOR_MAGNETIC_FIELD;
    682             case Sensor.TYPE_ORIENTATION:
    683                 return SENSOR_ORIENTATION_RAW;
    684             case Sensor.TYPE_TEMPERATURE:
    685                 return SENSOR_TEMPERATURE;
    686         }
    687         return 0;
    688     }
    689 
    690     /**
    691      * @return available sensors.
    692      * @deprecated This method is deprecated, use
    693      *             {@link SensorManager#getSensorList(int)} instead
    694      */
    695     @Deprecated
    696     public int getSensors() {
    697         int result = 0;
    698         final ArrayList<Sensor> fullList = sFullSensorsList;
    699         for (Sensor i : fullList) {
    700             switch (i.getType()) {
    701                 case Sensor.TYPE_ACCELEROMETER:
    702                     result |= SensorManager.SENSOR_ACCELEROMETER;
    703                     break;
    704                 case Sensor.TYPE_MAGNETIC_FIELD:
    705                     result |= SensorManager.SENSOR_MAGNETIC_FIELD;
    706                     break;
    707                 case Sensor.TYPE_ORIENTATION:
    708                     result |= SensorManager.SENSOR_ORIENTATION |
    709                     SensorManager.SENSOR_ORIENTATION_RAW;
    710                     break;
    711             }
    712         }
    713         return result;
    714     }
    715 
    716     /**
    717      * Use this method to get the list of available sensors of a certain type.
    718      * Make multiple calls to get sensors of different types or use
    719      * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the
    720      * sensors.
    721      *
    722      * @param type
    723      *        of sensors requested
    724      *
    725      * @return a list of sensors matching the asked type.
    726      *
    727      * @see #getDefaultSensor(int)
    728      * @see Sensor
    729      */
    730     public List<Sensor> getSensorList(int type) {
    731         // cache the returned lists the first time
    732         List<Sensor> list;
    733         final ArrayList<Sensor> fullList = sFullSensorsList;
    734         synchronized(fullList) {
    735             list = sSensorListByType.get(type);
    736             if (list == null) {
    737                 if (type == Sensor.TYPE_ALL) {
    738                     list = fullList;
    739                 } else {
    740                     list = new ArrayList<Sensor>();
    741                     for (Sensor i : fullList) {
    742                         if (i.getType() == type)
    743                             list.add(i);
    744                     }
    745                 }
    746                 list = Collections.unmodifiableList(list);
    747                 sSensorListByType.append(type, list);
    748             }
    749         }
    750         return list;
    751     }
    752 
    753     /**
    754      * Use this method to get the default sensor for a given type. Note that the
    755      * returned sensor could be a composite sensor, and its data could be
    756      * averaged or filtered. If you need to access the raw sensors use
    757      * {@link SensorManager#getSensorList(int) getSensorList}.
    758      *
    759      * @param type
    760      *        of sensors requested
    761      *
    762      * @return the default sensors matching the asked type.
    763      *
    764      * @see #getSensorList(int)
    765      * @see Sensor
    766      */
    767     public Sensor getDefaultSensor(int type) {
    768         // TODO: need to be smarter, for now, just return the 1st sensor
    769         List<Sensor> l = getSensorList(type);
    770         return l.isEmpty() ? null : l.get(0);
    771     }
    772 
    773     /**
    774      * Registers a listener for given sensors.
    775      *
    776      * @deprecated This method is deprecated, use
    777      *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
    778      *             instead.
    779      *
    780      * @param listener
    781      *        sensor listener object
    782      *
    783      * @param sensors
    784      *        a bit masks of the sensors to register to
    785      *
    786      * @return <code>true</code> if the sensor is supported and successfully
    787      *         enabled
    788      */
    789     @Deprecated
    790     public boolean registerListener(SensorListener listener, int sensors) {
    791         return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
    792     }
    793 
    794     /**
    795      * Registers a SensorListener for given sensors.
    796      *
    797      * @deprecated This method is deprecated, use
    798      *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
    799      *             instead.
    800      *
    801      * @param listener
    802      *        sensor listener object
    803      *
    804      * @param sensors
    805      *        a bit masks of the sensors to register to
    806      *
    807      * @param rate
    808      *        rate of events. This is only a hint to the system. events may be
    809      *        received faster or slower than the specified rate. Usually events
    810      *        are received faster. The value must be one of
    811      *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
    812      *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
    813      *
    814      * @return <code>true</code> if the sensor is supported and successfully
    815      *         enabled
    816      */
    817     @Deprecated
    818     public boolean registerListener(SensorListener listener, int sensors, int rate) {
    819         if (listener == null) {
    820             return false;
    821         }
    822         boolean result = false;
    823         result = registerLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
    824                 listener, sensors, rate) || result;
    825         result = registerLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
    826                 listener, sensors, rate) || result;
    827         result = registerLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
    828                 listener, sensors, rate) || result;
    829         result = registerLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
    830                 listener, sensors, rate) || result;
    831         result = registerLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
    832                 listener, sensors, rate) || result;
    833         return result;
    834     }
    835 
    836     @SuppressWarnings("deprecation")
    837     private boolean registerLegacyListener(int legacyType, int type,
    838             SensorListener listener, int sensors, int rate)
    839     {
    840         if (listener == null) {
    841             return false;
    842         }
    843         boolean result = false;
    844         // Are we activating this legacy sensor?
    845         if ((sensors & legacyType) != 0) {
    846             // if so, find a suitable Sensor
    847             Sensor sensor = getDefaultSensor(type);
    848             if (sensor != null) {
    849                 // If we don't already have one, create a LegacyListener
    850                 // to wrap this listener and process the events as
    851                 // they are expected by legacy apps.
    852                 LegacyListener legacyListener = null;
    853                 synchronized (mLegacyListenersMap) {
    854                     legacyListener = mLegacyListenersMap.get(listener);
    855                     if (legacyListener == null) {
    856                         // we didn't find a LegacyListener for this client,
    857                         // create one, and put it in our list.
    858                         legacyListener = new LegacyListener(listener);
    859                         mLegacyListenersMap.put(listener, legacyListener);
    860                     }
    861                 }
    862                 // register this legacy sensor with this legacy listener
    863                 legacyListener.registerSensor(legacyType);
    864                 // and finally, register the legacy listener with the new apis
    865                 result = registerListener(legacyListener, sensor, rate);
    866             }
    867         }
    868         return result;
    869     }
    870 
    871     /**
    872      * Unregisters a listener for the sensors with which it is registered.
    873      *
    874      * @deprecated This method is deprecated, use
    875      *             {@link SensorManager#unregisterListener(SensorEventListener, Sensor)}
    876      *             instead.
    877      *
    878      * @param listener
    879      *        a SensorListener object
    880      *
    881      * @param sensors
    882      *        a bit masks of the sensors to unregister from
    883      */
    884     @Deprecated
    885     public void unregisterListener(SensorListener listener, int sensors) {
    886         unregisterLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
    887                 listener, sensors);
    888         unregisterLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
    889                 listener, sensors);
    890         unregisterLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
    891                 listener, sensors);
    892         unregisterLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
    893                 listener, sensors);
    894         unregisterLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
    895                 listener, sensors);
    896     }
    897 
    898     @SuppressWarnings("deprecation")
    899     private void unregisterLegacyListener(int legacyType, int type,
    900             SensorListener listener, int sensors)
    901     {
    902         if (listener == null) {
    903             return;
    904         }
    905         // do we know about this listener?
    906         LegacyListener legacyListener = null;
    907         synchronized (mLegacyListenersMap) {
    908             legacyListener = mLegacyListenersMap.get(listener);
    909         }
    910         if (legacyListener != null) {
    911             // Are we deactivating this legacy sensor?
    912             if ((sensors & legacyType) != 0) {
    913                 // if so, find the corresponding Sensor
    914                 Sensor sensor = getDefaultSensor(type);
    915                 if (sensor != null) {
    916                     // unregister this legacy sensor and if we don't
    917                     // need the corresponding Sensor, unregister it too
    918                     if (legacyListener.unregisterSensor(legacyType)) {
    919                         // corresponding sensor not needed, unregister
    920                         unregisterListener(legacyListener, sensor);
    921                         // finally check if we still need the legacyListener
    922                         // in our mapping, if not, get rid of it too.
    923                         synchronized(sListeners) {
    924                             boolean found = false;
    925                             for (ListenerDelegate i : sListeners) {
    926                                 if (i.getListener() == legacyListener) {
    927                                     found = true;
    928                                     break;
    929                                 }
    930                             }
    931                             if (!found) {
    932                                 synchronized (mLegacyListenersMap) {
    933                                     mLegacyListenersMap.remove(listener);
    934                                 }
    935                             }
    936                         }
    937                     }
    938                 }
    939             }
    940         }
    941     }
    942 
    943     /**
    944      * Unregisters a listener for all sensors.
    945      *
    946      * @deprecated This method is deprecated, use
    947      *             {@link SensorManager#unregisterListener(SensorEventListener)}
    948      *             instead.
    949      *
    950      * @param listener
    951      *        a SensorListener object
    952      */
    953     @Deprecated
    954     public void unregisterListener(SensorListener listener) {
    955         unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
    956     }
    957 
    958     /**
    959      * Unregisters a listener for the sensors with which it is registered.
    960      *
    961      * @param listener
    962      *        a SensorEventListener object
    963      *
    964      * @param sensor
    965      *        the sensor to unregister from
    966      *
    967      * @see #unregisterListener(SensorEventListener)
    968      * @see #registerListener(SensorEventListener, Sensor, int)
    969      *
    970      */
    971     public void unregisterListener(SensorEventListener listener, Sensor sensor) {
    972         unregisterListener((Object)listener, sensor);
    973     }
    974 
    975     /**
    976      * Unregisters a listener for all sensors.
    977      *
    978      * @param listener
    979      *        a SensorListener object
    980      *
    981      * @see #unregisterListener(SensorEventListener, Sensor)
    982      * @see #registerListener(SensorEventListener, Sensor, int)
    983      *
    984      */
    985     public void unregisterListener(SensorEventListener listener) {
    986         unregisterListener((Object)listener);
    987     }
    988 
    989     /**
    990      * Registers a {@link android.hardware.SensorEventListener
    991      * SensorEventListener} for the given sensor.
    992      *
    993      * @param listener
    994      *        A {@link android.hardware.SensorEventListener SensorEventListener}
    995      *        object.
    996      *
    997      * @param sensor
    998      *        The {@link android.hardware.Sensor Sensor} to register to.
    999      *
   1000      * @param rate
   1001      *        The rate {@link android.hardware.SensorEvent sensor events} are
   1002      *        delivered at. This is only a hint to the system. Events may be
   1003      *        received faster or slower than the specified rate. Usually events
   1004      *        are received faster. The value must be one of
   1005      *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
   1006      *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}
   1007      *        or, the desired delay between events in microsecond.
   1008      *
   1009      * @return <code>true</code> if the sensor is supported and successfully
   1010      *         enabled.
   1011      *
   1012      * @see #registerListener(SensorEventListener, Sensor, int, Handler)
   1013      * @see #unregisterListener(SensorEventListener)
   1014      * @see #unregisterListener(SensorEventListener, Sensor)
   1015      *
   1016      */
   1017     public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {
   1018         return registerListener(listener, sensor, rate, null);
   1019     }
   1020 
   1021     private boolean enableSensorLocked(Sensor sensor, int delay) {
   1022         boolean result = false;
   1023         for (ListenerDelegate i : sListeners) {
   1024             if (i.hasSensor(sensor)) {
   1025                 String name = sensor.getName();
   1026                 int handle = sensor.getHandle();
   1027                 result = sensors_enable_sensor(sQueue, name, handle, delay);
   1028                 break;
   1029             }
   1030         }
   1031         return result;
   1032     }
   1033 
   1034     private boolean disableSensorLocked(Sensor sensor) {
   1035         for (ListenerDelegate i : sListeners) {
   1036             if (i.hasSensor(sensor)) {
   1037                 // not an error, it's just that this sensor is still in use
   1038                 return true;
   1039             }
   1040         }
   1041         String name = sensor.getName();
   1042         int handle = sensor.getHandle();
   1043         return sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
   1044     }
   1045 
   1046     /**
   1047      * Registers a {@link android.hardware.SensorEventListener
   1048      * SensorEventListener} for the given sensor.
   1049      *
   1050      * @param listener
   1051      *        A {@link android.hardware.SensorEventListener SensorEventListener}
   1052      *        object.
   1053      *
   1054      * @param sensor
   1055      *        The {@link android.hardware.Sensor Sensor} to register to.
   1056      *
   1057      * @param rate
   1058      *        The rate {@link android.hardware.SensorEvent sensor events} are
   1059      *        delivered at. This is only a hint to the system. Events may be
   1060      *        received faster or slower than the specified rate. Usually events
   1061      *        are received faster. The value must be one of
   1062      *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
   1063      *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
   1064      *        or, the desired delay between events in microsecond.
   1065      *
   1066      * @param handler
   1067      *        The {@link android.os.Handler Handler} the
   1068      *        {@link android.hardware.SensorEvent sensor events} will be
   1069      *        delivered to.
   1070      *
   1071      * @return true if the sensor is supported and successfully enabled.
   1072      *
   1073      * @see #registerListener(SensorEventListener, Sensor, int)
   1074      * @see #unregisterListener(SensorEventListener)
   1075      * @see #unregisterListener(SensorEventListener, Sensor)
   1076      *
   1077      */
   1078     public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,
   1079             Handler handler) {
   1080         if (listener == null || sensor == null) {
   1081             return false;
   1082         }
   1083         boolean result = true;
   1084         int delay = -1;
   1085         switch (rate) {
   1086             case SENSOR_DELAY_FASTEST:
   1087                 delay = 0;
   1088                 break;
   1089             case SENSOR_DELAY_GAME:
   1090                 delay = 20000;
   1091                 break;
   1092             case SENSOR_DELAY_UI:
   1093                 delay = 66667;
   1094                 break;
   1095             case SENSOR_DELAY_NORMAL:
   1096                 delay = 200000;
   1097                 break;
   1098             default:
   1099                 delay = rate;
   1100                 break;
   1101         }
   1102 
   1103         synchronized (sListeners) {
   1104             // look for this listener in our list
   1105             ListenerDelegate l = null;
   1106             for (ListenerDelegate i : sListeners) {
   1107                 if (i.getListener() == listener) {
   1108                     l = i;
   1109                     break;
   1110                 }
   1111             }
   1112 
   1113             // if we don't find it, add it to the list
   1114             if (l == null) {
   1115                 l = new ListenerDelegate(listener, sensor, handler);
   1116                 sListeners.add(l);
   1117                 // if the list is not empty, start our main thread
   1118                 if (!sListeners.isEmpty()) {
   1119                     if (sSensorThread.startLocked()) {
   1120                         if (!enableSensorLocked(sensor, delay)) {
   1121                             // oops. there was an error
   1122                             sListeners.remove(l);
   1123                             result = false;
   1124                         }
   1125                     } else {
   1126                         // there was an error, remove the listener
   1127                         sListeners.remove(l);
   1128                         result = false;
   1129                     }
   1130                 } else {
   1131                     // weird, we couldn't add the listener
   1132                     result = false;
   1133                 }
   1134             } else {
   1135                 l.addSensor(sensor);
   1136                 if (!enableSensorLocked(sensor, delay)) {
   1137                     // oops. there was an error
   1138                     l.removeSensor(sensor);
   1139                     result = false;
   1140                 }
   1141             }
   1142         }
   1143 
   1144         return result;
   1145     }
   1146 
   1147     private void unregisterListener(Object listener, Sensor sensor) {
   1148         if (listener == null || sensor == null) {
   1149             return;
   1150         }
   1151 
   1152         synchronized (sListeners) {
   1153             final int size = sListeners.size();
   1154             for (int i=0 ; i<size ; i++) {
   1155                 ListenerDelegate l = sListeners.get(i);
   1156                 if (l.getListener() == listener) {
   1157                     if (l.removeSensor(sensor) == 0) {
   1158                         // if we have no more sensors enabled on this listener,
   1159                         // take it off the list.
   1160                         sListeners.remove(i);
   1161                     }
   1162                     break;
   1163                 }
   1164             }
   1165             disableSensorLocked(sensor);
   1166         }
   1167     }
   1168 
   1169     private void unregisterListener(Object listener) {
   1170         if (listener == null) {
   1171             return;
   1172         }
   1173 
   1174         synchronized (sListeners) {
   1175             final int size = sListeners.size();
   1176             for (int i=0 ; i<size ; i++) {
   1177                 ListenerDelegate l = sListeners.get(i);
   1178                 if (l.getListener() == listener) {
   1179                     sListeners.remove(i);
   1180                     // disable all sensors for this listener
   1181                     for (Sensor sensor : l.getSensors()) {
   1182                         disableSensorLocked(sensor);
   1183                     }
   1184                     break;
   1185                 }
   1186             }
   1187         }
   1188     }
   1189 
   1190     /**
   1191      * <p>
   1192      * Computes the inclination matrix <b>I</b> as well as the rotation matrix
   1193      * <b>R</b> transforming a vector from the device coordinate system to the
   1194      * world's coordinate system which is defined as a direct orthonormal basis,
   1195      * where:
   1196      * </p>
   1197      *
   1198      * <ul>
   1199      * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
   1200      * the ground at the device's current location and roughly points East).</li>
   1201      * <li>Y is tangential to the ground at the device's current location and
   1202      * points towards the magnetic North Pole.</li>
   1203      * <li>Z points towards the sky and is perpendicular to the ground.</li>
   1204      * </ul>
   1205      *
   1206      * <p>
   1207      * <center><img src="../../../images/axis_globe.png"
   1208      * alt="World coordinate-system diagram." border="0" /></center>
   1209      * </p>
   1210      *
   1211      * <p>
   1212      * <hr>
   1213      * <p>
   1214      * By definition:
   1215      * <p>
   1216      * [0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity)
   1217      * <p>
   1218      * [0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b> (m = magnitude of
   1219      * geomagnetic field)
   1220      * <p>
   1221      * <b>R</b> is the identity matrix when the device is aligned with the
   1222      * world's coordinate system, that is, when the device's X axis points
   1223      * toward East, the Y axis points to the North Pole and the device is facing
   1224      * the sky.
   1225      *
   1226      * <p>
   1227      * <b>I</b> is a rotation matrix transforming the geomagnetic vector into
   1228      * the same coordinate space as gravity (the world's coordinate space).
   1229      * <b>I</b> is a simple rotation around the X axis. The inclination angle in
   1230      * radians can be computed with {@link #getInclination}.
   1231      * <hr>
   1232      *
   1233      * <p>
   1234      * Each matrix is returned either as a 3x3 or 4x4 row-major matrix depending
   1235      * on the length of the passed array:
   1236      * <p>
   1237      * <u>If the array length is 16:</u>
   1238      *
   1239      * <pre>
   1240      *   /  M[ 0]   M[ 1]   M[ 2]   M[ 3]  \
   1241      *   |  M[ 4]   M[ 5]   M[ 6]   M[ 7]  |
   1242      *   |  M[ 8]   M[ 9]   M[10]   M[11]  |
   1243      *   \  M[12]   M[13]   M[14]   M[15]  /
   1244      *</pre>
   1245      *
   1246      * This matrix is ready to be used by OpenGL ES's
   1247      * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int)
   1248      * glLoadMatrixf(float[], int)}.
   1249      * <p>
   1250      * Note that because OpenGL matrices are column-major matrices you must
   1251      * transpose the matrix before using it. However, since the matrix is a
   1252      * rotation matrix, its transpose is also its inverse, conveniently, it is
   1253      * often the inverse of the rotation that is needed for rendering; it can
   1254      * therefore be used with OpenGL ES directly.
   1255      * <p>
   1256      * Also note that the returned matrices always have this form:
   1257      *
   1258      * <pre>
   1259      *   /  M[ 0]   M[ 1]   M[ 2]   0  \
   1260      *   |  M[ 4]   M[ 5]   M[ 6]   0  |
   1261      *   |  M[ 8]   M[ 9]   M[10]   0  |
   1262      *   \      0       0       0   1  /
   1263      *</pre>
   1264      *
   1265      * <p>
   1266      * <u>If the array length is 9:</u>
   1267      *
   1268      * <pre>
   1269      *   /  M[ 0]   M[ 1]   M[ 2]  \
   1270      *   |  M[ 3]   M[ 4]   M[ 5]  |
   1271      *   \  M[ 6]   M[ 7]   M[ 8]  /
   1272      *</pre>
   1273      *
   1274      * <hr>
   1275      * <p>
   1276      * The inverse of each matrix can be computed easily by taking its
   1277      * transpose.
   1278      *
   1279      * <p>
   1280      * The matrices returned by this function are meaningful only when the
   1281      * device is not free-falling and it is not close to the magnetic north. If
   1282      * the device is accelerating, or placed into a strong magnetic field, the
   1283      * returned matrices may be inaccurate.
   1284      *
   1285      * @param R
   1286      *        is an array of 9 floats holding the rotation matrix <b>R</b> when
   1287      *        this function returns. R can be null.
   1288      *        <p>
   1289      *
   1290      * @param I
   1291      *        is an array of 9 floats holding the rotation matrix <b>I</b> when
   1292      *        this function returns. I can be null.
   1293      *        <p>
   1294      *
   1295      * @param gravity
   1296      *        is an array of 3 floats containing the gravity vector expressed in
   1297      *        the device's coordinate. You can simply use the
   1298      *        {@link android.hardware.SensorEvent#values values} returned by a
   1299      *        {@link android.hardware.SensorEvent SensorEvent} of a
   1300      *        {@link android.hardware.Sensor Sensor} of type
   1301      *        {@link android.hardware.Sensor#TYPE_ACCELEROMETER
   1302      *        TYPE_ACCELEROMETER}.
   1303      *        <p>
   1304      *
   1305      * @param geomagnetic
   1306      *        is an array of 3 floats containing the geomagnetic vector
   1307      *        expressed in the device's coordinate. You can simply use the
   1308      *        {@link android.hardware.SensorEvent#values values} returned by a
   1309      *        {@link android.hardware.SensorEvent SensorEvent} of a
   1310      *        {@link android.hardware.Sensor Sensor} of type
   1311      *        {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD
   1312      *        TYPE_MAGNETIC_FIELD}.
   1313      *
   1314      * @return <code>true</code> on success, <code>false</code> on failure (for
   1315      *         instance, if the device is in free fall). On failure the output
   1316      *         matrices are not modified.
   1317      *
   1318      * @see #getInclination(float[])
   1319      * @see #getOrientation(float[], float[])
   1320      * @see #remapCoordinateSystem(float[], int, int, float[])
   1321      */
   1322 
   1323     public static boolean getRotationMatrix(float[] R, float[] I,
   1324             float[] gravity, float[] geomagnetic) {
   1325         // TODO: move this to native code for efficiency
   1326         float Ax = gravity[0];
   1327         float Ay = gravity[1];
   1328         float Az = gravity[2];
   1329         final float Ex = geomagnetic[0];
   1330         final float Ey = geomagnetic[1];
   1331         final float Ez = geomagnetic[2];
   1332         float Hx = Ey*Az - Ez*Ay;
   1333         float Hy = Ez*Ax - Ex*Az;
   1334         float Hz = Ex*Ay - Ey*Ax;
   1335         final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
   1336         if (normH < 0.1f) {
   1337             // device is close to free fall (or in space?), or close to
   1338             // magnetic north pole. Typical values are  > 100.
   1339             return false;
   1340         }
   1341         final float invH = 1.0f / normH;
   1342         Hx *= invH;
   1343         Hy *= invH;
   1344         Hz *= invH;
   1345         final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
   1346         Ax *= invA;
   1347         Ay *= invA;
   1348         Az *= invA;
   1349         final float Mx = Ay*Hz - Az*Hy;
   1350         final float My = Az*Hx - Ax*Hz;
   1351         final float Mz = Ax*Hy - Ay*Hx;
   1352         if (R != null) {
   1353             if (R.length == 9) {
   1354                 R[0] = Hx;     R[1] = Hy;     R[2] = Hz;
   1355                 R[3] = Mx;     R[4] = My;     R[5] = Mz;
   1356                 R[6] = Ax;     R[7] = Ay;     R[8] = Az;
   1357             } else if (R.length == 16) {
   1358                 R[0]  = Hx;    R[1]  = Hy;    R[2]  = Hz;   R[3]  = 0;
   1359                 R[4]  = Mx;    R[5]  = My;    R[6]  = Mz;   R[7]  = 0;
   1360                 R[8]  = Ax;    R[9]  = Ay;    R[10] = Az;   R[11] = 0;
   1361                 R[12] = 0;     R[13] = 0;     R[14] = 0;    R[15] = 1;
   1362             }
   1363         }
   1364         if (I != null) {
   1365             // compute the inclination matrix by projecting the geomagnetic
   1366             // vector onto the Z (gravity) and X (horizontal component
   1367             // of geomagnetic vector) axes.
   1368             final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
   1369             final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
   1370             final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
   1371             if (I.length == 9) {
   1372                 I[0] = 1;     I[1] = 0;     I[2] = 0;
   1373                 I[3] = 0;     I[4] = c;     I[5] = s;
   1374                 I[6] = 0;     I[7] =-s;     I[8] = c;
   1375             } else if (I.length == 16) {
   1376                 I[0] = 1;     I[1] = 0;     I[2] = 0;
   1377                 I[4] = 0;     I[5] = c;     I[6] = s;
   1378                 I[8] = 0;     I[9] =-s;     I[10]= c;
   1379                 I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
   1380                 I[15] = 1;
   1381             }
   1382         }
   1383         return true;
   1384     }
   1385 
   1386     /**
   1387      * Computes the geomagnetic inclination angle in radians from the
   1388      * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}.
   1389      *
   1390      * @param I
   1391      *        inclination matrix see {@link #getRotationMatrix}.
   1392      *
   1393      * @return The geomagnetic inclination angle in radians.
   1394      *
   1395      * @see #getRotationMatrix(float[], float[], float[], float[])
   1396      * @see #getOrientation(float[], float[])
   1397      * @see GeomagneticField
   1398      *
   1399      */
   1400     public static float getInclination(float[] I) {
   1401         if (I.length == 9) {
   1402             return (float)Math.atan2(I[5], I[4]);
   1403         } else {
   1404             return (float)Math.atan2(I[6], I[5]);
   1405         }
   1406     }
   1407 
   1408     /**
   1409      * <p>
   1410      * Rotates the supplied rotation matrix so it is expressed in a different
   1411      * coordinate system. This is typically used when an application needs to
   1412      * compute the three orientation angles of the device (see
   1413      * {@link #getOrientation}) in a different coordinate system.
   1414      * </p>
   1415      *
   1416      * <p>
   1417      * When the rotation matrix is used for drawing (for instance with OpenGL
   1418      * ES), it usually <b>doesn't need</b> to be transformed by this function,
   1419      * unless the screen is physically rotated, in which case you can use
   1420      * {@link android.view.Display#getRotation() Display.getRotation()} to
   1421      * retrieve the current rotation of the screen. Note that because the user
   1422      * is generally free to rotate their screen, you often should consider the
   1423      * rotation in deciding the parameters to use here.
   1424      * </p>
   1425      *
   1426      * <p>
   1427      * <u>Examples:</u>
   1428      * <p>
   1429      *
   1430      * <ul>
   1431      * <li>Using the camera (Y axis along the camera's axis) for an augmented
   1432      * reality application where the rotation angles are needed:</li>
   1433      *
   1434      * <p>
   1435      * <ul>
   1436      * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code>
   1437      * </ul>
   1438      * </p>
   1439      *
   1440      * <li>Using the device as a mechanical compass when rotation is
   1441      * {@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:</li>
   1442      *
   1443      * <p>
   1444      * <ul>
   1445      * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code>
   1446      * </ul>
   1447      * </p>
   1448      *
   1449      * Beware of the above example. This call is needed only to account for a
   1450      * rotation from its natural orientation when calculating the rotation
   1451      * angles (see {@link #getOrientation}). If the rotation matrix is also used
   1452      * for rendering, it may not need to be transformed, for instance if your
   1453      * {@link android.app.Activity Activity} is running in landscape mode.
   1454      * </ul>
   1455      *
   1456      * <p>
   1457      * Since the resulting coordinate system is orthonormal, only two axes need
   1458      * to be specified.
   1459      *
   1460      * @param inR
   1461      *        the rotation matrix to be transformed. Usually it is the matrix
   1462      *        returned by {@link #getRotationMatrix}.
   1463      *
   1464      * @param X
   1465      *        defines on which world axis and direction the X axis of the device
   1466      *        is mapped.
   1467      *
   1468      * @param Y
   1469      *        defines on which world axis and direction the Y axis of the device
   1470      *        is mapped.
   1471      *
   1472      * @param outR
   1473      *        the transformed rotation matrix. inR and outR can be the same
   1474      *        array, but it is not recommended for performance reason.
   1475      *
   1476      * @return <code>true</code> on success. <code>false</code> if the input
   1477      *         parameters are incorrect, for instance if X and Y define the same
   1478      *         axis. Or if inR and outR don't have the same length.
   1479      *
   1480      * @see #getRotationMatrix(float[], float[], float[], float[])
   1481      */
   1482 
   1483     public static boolean remapCoordinateSystem(float[] inR, int X, int Y,
   1484             float[] outR)
   1485     {
   1486         if (inR == outR) {
   1487             final float[] temp = mTempMatrix;
   1488             synchronized(temp) {
   1489                 // we don't expect to have a lot of contention
   1490                 if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
   1491                     final int size = outR.length;
   1492                     for (int i=0 ; i<size ; i++)
   1493                         outR[i] = temp[i];
   1494                     return true;
   1495                 }
   1496             }
   1497         }
   1498         return remapCoordinateSystemImpl(inR, X, Y, outR);
   1499     }
   1500 
   1501     private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y,
   1502             float[] outR)
   1503     {
   1504         /*
   1505          * X and Y define a rotation matrix 'r':
   1506          *
   1507          *  (X==1)?((X&0x80)?-1:1):0    (X==2)?((X&0x80)?-1:1):0    (X==3)?((X&0x80)?-1:1):0
   1508          *  (Y==1)?((Y&0x80)?-1:1):0    (Y==2)?((Y&0x80)?-1:1):0    (Y==3)?((X&0x80)?-1:1):0
   1509          *                              r[0] ^ r[1]
   1510          *
   1511          * where the 3rd line is the vector product of the first 2 lines
   1512          *
   1513          */
   1514 
   1515         final int length = outR.length;
   1516         if (inR.length != length)
   1517             return false;   // invalid parameter
   1518         if ((X & 0x7C)!=0 || (Y & 0x7C)!=0)
   1519             return false;   // invalid parameter
   1520         if (((X & 0x3)==0) || ((Y & 0x3)==0))
   1521             return false;   // no axis specified
   1522         if ((X & 0x3) == (Y & 0x3))
   1523             return false;   // same axis specified
   1524 
   1525         // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
   1526         // this can be calculated by exclusive-or'ing X and Y; except for
   1527         // the sign inversion (+/-) which is calculated below.
   1528         int Z = X ^ Y;
   1529 
   1530         // extract the axis (remove the sign), offset in the range 0 to 2.
   1531         final int x = (X & 0x3)-1;
   1532         final int y = (Y & 0x3)-1;
   1533         final int z = (Z & 0x3)-1;
   1534 
   1535         // compute the sign of Z (whether it needs to be inverted)
   1536         final int axis_y = (z+1)%3;
   1537         final int axis_z = (z+2)%3;
   1538         if (((x^axis_y)|(y^axis_z)) != 0)
   1539             Z ^= 0x80;
   1540 
   1541         final boolean sx = (X>=0x80);
   1542         final boolean sy = (Y>=0x80);
   1543         final boolean sz = (Z>=0x80);
   1544 
   1545         // Perform R * r, in avoiding actual muls and adds.
   1546         final int rowLength = ((length==16)?4:3);
   1547         for (int j=0 ; j<3 ; j++) {
   1548             final int offset = j*rowLength;
   1549             for (int i=0 ; i<3 ; i++) {
   1550                 if (x==i)   outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0];
   1551                 if (y==i)   outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1];
   1552                 if (z==i)   outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2];
   1553             }
   1554         }
   1555         if (length == 16) {
   1556             outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
   1557             outR[15] = 1;
   1558         }
   1559         return true;
   1560     }
   1561 
   1562     /**
   1563      * Computes the device's orientation based on the rotation matrix.
   1564      * <p>
   1565      * When it returns, the array values is filled with the result:
   1566      * <ul>
   1567      * <li>values[0]: <i>azimuth</i>, rotation around the Z axis.</li>
   1568      * <li>values[1]: <i>pitch</i>, rotation around the X axis.</li>
   1569      * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li>
   1570      * </ul>
   1571      * <p>The reference coordinate-system used is different from the world
   1572      * coordinate-system defined for the rotation matrix:</p>
   1573      * <ul>
   1574      * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
   1575      * the ground at the device's current location and roughly points West).</li>
   1576      * <li>Y is tangential to the ground at the device's current location and
   1577      * points towards the magnetic North Pole.</li>
   1578      * <li>Z points towards the center of the Earth and is perpendicular to the ground.</li>
   1579      * </ul>
   1580      *
   1581      * <p>
   1582      * <center><img src="../../../images/axis_globe_inverted.png"
   1583      * alt="Inverted world coordinate-system diagram." border="0" /></center>
   1584      * </p>
   1585      * <p>
   1586      * All three angles above are in <b>radians</b> and <b>positive</b> in the
   1587      * <b>counter-clockwise</b> direction.
   1588      *
   1589      * @param R
   1590      *        rotation matrix see {@link #getRotationMatrix}.
   1591      *
   1592      * @param values
   1593      *        an array of 3 floats to hold the result.
   1594      *
   1595      * @return The array values passed as argument.
   1596      *
   1597      * @see #getRotationMatrix(float[], float[], float[], float[])
   1598      * @see GeomagneticField
   1599      */
   1600     public static float[] getOrientation(float[] R, float values[]) {
   1601         /*
   1602          * 4x4 (length=16) case:
   1603          *   /  R[ 0]   R[ 1]   R[ 2]   0  \
   1604          *   |  R[ 4]   R[ 5]   R[ 6]   0  |
   1605          *   |  R[ 8]   R[ 9]   R[10]   0  |
   1606          *   \      0       0       0   1  /
   1607          *
   1608          * 3x3 (length=9) case:
   1609          *   /  R[ 0]   R[ 1]   R[ 2]  \
   1610          *   |  R[ 3]   R[ 4]   R[ 5]  |
   1611          *   \  R[ 6]   R[ 7]   R[ 8]  /
   1612          *
   1613          */
   1614         if (R.length == 9) {
   1615             values[0] = (float)Math.atan2(R[1], R[4]);
   1616             values[1] = (float)Math.asin(-R[7]);
   1617             values[2] = (float)Math.atan2(-R[6], R[8]);
   1618         } else {
   1619             values[0] = (float)Math.atan2(R[1], R[5]);
   1620             values[1] = (float)Math.asin(-R[9]);
   1621             values[2] = (float)Math.atan2(-R[8], R[10]);
   1622         }
   1623         return values;
   1624     }
   1625 
   1626     /**
   1627      * Computes the Altitude in meters from the atmospheric pressure and the
   1628      * pressure at sea level.
   1629      * <p>
   1630      * Typically the atmospheric pressure is read from a
   1631      * {@link Sensor#TYPE_PRESSURE} sensor. The pressure at sea level must be
   1632      * known, usually it can be retrieved from airport databases in the
   1633      * vicinity. If unknown, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE}
   1634      * as an approximation, but absolute altitudes won't be accurate.
   1635      * </p>
   1636      * <p>
   1637      * To calculate altitude differences, you must calculate the difference
   1638      * between the altitudes at both points. If you don't know the altitude
   1639      * as sea level, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE} instead,
   1640      * which will give good results considering the range of pressure typically
   1641      * involved.
   1642      * </p>
   1643      * <p>
   1644      * <code><ul>
   1645      *  float altitude_difference =
   1646      *      getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point2)
   1647      *      - getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point1);
   1648      * </ul></code>
   1649      * </p>
   1650      *
   1651      * @param p0 pressure at sea level
   1652      * @param p atmospheric pressure
   1653      * @return Altitude in meters
   1654      */
   1655    public static float getAltitude(float p0, float p) {
   1656         final float coef = 1.0f / 5.255f;
   1657         return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef));
   1658     }
   1659 
   1660 
   1661    /**
   1662      * {@hide}
   1663      */
   1664     public void onRotationChanged(int rotation) {
   1665         synchronized(sListeners) {
   1666             sRotation  = rotation;
   1667         }
   1668     }
   1669 
   1670     static int getRotation() {
   1671         synchronized(sListeners) {
   1672             return sRotation;
   1673         }
   1674     }
   1675 
   1676     private class LegacyListener implements SensorEventListener {
   1677         private float mValues[] = new float[6];
   1678         @SuppressWarnings("deprecation")
   1679         private SensorListener mTarget;
   1680         private int mSensors;
   1681         private final LmsFilter mYawfilter = new LmsFilter();
   1682 
   1683         @SuppressWarnings("deprecation")
   1684         LegacyListener(SensorListener target) {
   1685             mTarget = target;
   1686             mSensors = 0;
   1687         }
   1688 
   1689         void registerSensor(int legacyType) {
   1690             mSensors |= legacyType;
   1691         }
   1692 
   1693         boolean unregisterSensor(int legacyType) {
   1694             mSensors &= ~legacyType;
   1695             int mask = SENSOR_ORIENTATION|SENSOR_ORIENTATION_RAW;
   1696             if (((legacyType&mask)!=0) && ((mSensors&mask)!=0)) {
   1697                 return false;
   1698             }
   1699             return true;
   1700         }
   1701 
   1702         @SuppressWarnings("deprecation")
   1703         public void onAccuracyChanged(Sensor sensor, int accuracy) {
   1704             try {
   1705                 mTarget.onAccuracyChanged(sensor.getLegacyType(), accuracy);
   1706             } catch (AbstractMethodError e) {
   1707                 // old app that doesn't implement this method
   1708                 // just ignore it.
   1709             }
   1710         }
   1711 
   1712         @SuppressWarnings("deprecation")
   1713         public void onSensorChanged(SensorEvent event) {
   1714             final float v[] = mValues;
   1715             v[0] = event.values[0];
   1716             v[1] = event.values[1];
   1717             v[2] = event.values[2];
   1718             int legacyType = event.sensor.getLegacyType();
   1719             mapSensorDataToWindow(legacyType, v, SensorManager.getRotation());
   1720             if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
   1721                 if ((mSensors & SENSOR_ORIENTATION_RAW)!=0) {
   1722                     mTarget.onSensorChanged(SENSOR_ORIENTATION_RAW, v);
   1723                 }
   1724                 if ((mSensors & SENSOR_ORIENTATION)!=0) {
   1725                     v[0] = mYawfilter.filter(event.timestamp, v[0]);
   1726                     mTarget.onSensorChanged(SENSOR_ORIENTATION, v);
   1727                 }
   1728             } else {
   1729                 mTarget.onSensorChanged(legacyType, v);
   1730             }
   1731         }
   1732 
   1733         /*
   1734          * Helper function to convert the specified sensor's data to the windows's
   1735          * coordinate space from the device's coordinate space.
   1736          *
   1737          * output: 3,4,5: values in the old API format
   1738          *         0,1,2: transformed values in the old API format
   1739          *
   1740          */
   1741         private void mapSensorDataToWindow(int sensor,
   1742                 float[] values, int orientation) {
   1743             float x = values[0];
   1744             float y = values[1];
   1745             float z = values[2];
   1746 
   1747             switch (sensor) {
   1748                 case SensorManager.SENSOR_ORIENTATION:
   1749                 case SensorManager.SENSOR_ORIENTATION_RAW:
   1750                     z = -z;
   1751                     break;
   1752                 case SensorManager.SENSOR_ACCELEROMETER:
   1753                     x = -x;
   1754                     y = -y;
   1755                     z = -z;
   1756                     break;
   1757                 case SensorManager.SENSOR_MAGNETIC_FIELD:
   1758                     x = -x;
   1759                     y = -y;
   1760                     break;
   1761             }
   1762             values[0] = x;
   1763             values[1] = y;
   1764             values[2] = z;
   1765             values[3] = x;
   1766             values[4] = y;
   1767             values[5] = z;
   1768 
   1769             if ((orientation & Surface.ROTATION_90) != 0) {
   1770                 // handles 90 and 270 rotation
   1771                 switch (sensor) {
   1772                     case SENSOR_ACCELEROMETER:
   1773                     case SENSOR_MAGNETIC_FIELD:
   1774                         values[0] =-y;
   1775                         values[1] = x;
   1776                         values[2] = z;
   1777                         break;
   1778                     case SENSOR_ORIENTATION:
   1779                     case SENSOR_ORIENTATION_RAW:
   1780                         values[0] = x + ((x < 270) ? 90 : -270);
   1781                         values[1] = z;
   1782                         values[2] = y;
   1783                         break;
   1784                 }
   1785             }
   1786             if ((orientation & Surface.ROTATION_180) != 0) {
   1787                 x = values[0];
   1788                 y = values[1];
   1789                 z = values[2];
   1790                 // handles 180 (flip) and 270 (flip + 90) rotation
   1791                 switch (sensor) {
   1792                     case SENSOR_ACCELEROMETER:
   1793                     case SENSOR_MAGNETIC_FIELD:
   1794                         values[0] =-x;
   1795                         values[1] =-y;
   1796                         values[2] = z;
   1797                         break;
   1798                     case SENSOR_ORIENTATION:
   1799                     case SENSOR_ORIENTATION_RAW:
   1800                         values[0] = (x >= 180) ? (x - 180) : (x + 180);
   1801                         values[1] =-y;
   1802                         values[2] =-z;
   1803                         break;
   1804                 }
   1805             }
   1806         }
   1807     }
   1808 
   1809     class LmsFilter {
   1810         private static final int SENSORS_RATE_MS = 20;
   1811         private static final int COUNT = 12;
   1812         private static final float PREDICTION_RATIO = 1.0f/3.0f;
   1813         private static final float PREDICTION_TIME = (SENSORS_RATE_MS*COUNT/1000.0f)*PREDICTION_RATIO;
   1814         private float mV[] = new float[COUNT*2];
   1815         private float mT[] = new float[COUNT*2];
   1816         private int mIndex;
   1817 
   1818         public LmsFilter() {
   1819             mIndex = COUNT;
   1820         }
   1821 
   1822         public float filter(long time, float in) {
   1823             float v = in;
   1824             final float ns = 1.0f / 1000000000.0f;
   1825             final float t = time*ns;
   1826             float v1 = mV[mIndex];
   1827             if ((v-v1) > 180) {
   1828                 v -= 360;
   1829             } else if ((v1-v) > 180) {
   1830                 v += 360;
   1831             }
   1832             /* Manage the circular buffer, we write the data twice spaced
   1833              * by COUNT values, so that we don't have to copy the array
   1834              * when it's full
   1835              */
   1836             mIndex++;
   1837             if (mIndex >= COUNT*2)
   1838                 mIndex = COUNT;
   1839             mV[mIndex] = v;
   1840             mT[mIndex] = t;
   1841             mV[mIndex-COUNT] = v;
   1842             mT[mIndex-COUNT] = t;
   1843 
   1844             float A, B, C, D, E;
   1845             float a, b;
   1846             int i;
   1847 
   1848             A = B = C = D = E = 0;
   1849             for (i=0 ; i<COUNT-1 ; i++) {
   1850                 final int j = mIndex - 1 - i;
   1851                 final float Z = mV[j];
   1852                 final float T = 0.5f*(mT[j] + mT[j+1]) - t;
   1853                 float dT = mT[j] - mT[j+1];
   1854                 dT *= dT;
   1855                 A += Z*dT;
   1856                 B += T*(T*dT);
   1857                 C +=   (T*dT);
   1858                 D += Z*(T*dT);
   1859                 E += dT;
   1860             }
   1861             b = (A*B + C*D) / (E*B + C*C);
   1862             a = (E*b - A) / C;
   1863             float f = b + PREDICTION_TIME*a;
   1864 
   1865             // Normalize
   1866             f *= (1.0f / 360.0f);
   1867             if (((f>=0)?f:-f) >= 0.5f)
   1868                 f = f - (float)Math.ceil(f + 0.5f) + 1.0f;
   1869             if (f < 0)
   1870                 f += 1.0f;
   1871             f *= 360.0f;
   1872             return f;
   1873         }
   1874     }
   1875 
   1876 
   1877     /** Helper function to compute the angle change between two rotation matrices.
   1878      *  Given a current rotation matrix (R) and a previous rotation matrix
   1879      *  (prevR) computes the rotation around the x,y, and z axes which
   1880      *  transforms prevR to R.
   1881      *  outputs a 3 element vector containing the x,y, and z angle
   1882      *  change at indexes 0, 1, and 2 respectively.
   1883      * <p> Each input matrix is either as a 3x3 or 4x4 row-major matrix
   1884      * depending on the length of the passed array:
   1885      * <p>If the array length is 9, then the array elements represent this matrix
   1886      * <pre>
   1887      *   /  R[ 0]   R[ 1]   R[ 2]   \
   1888      *   |  R[ 3]   R[ 4]   R[ 5]   |
   1889      *   \  R[ 6]   R[ 7]   R[ 8]   /
   1890      *</pre>
   1891      * <p>If the array length is 16, then the array elements represent this matrix
   1892      * <pre>
   1893      *   /  R[ 0]   R[ 1]   R[ 2]   R[ 3]  \
   1894      *   |  R[ 4]   R[ 5]   R[ 6]   R[ 7]  |
   1895      *   |  R[ 8]   R[ 9]   R[10]   R[11]  |
   1896      *   \  R[12]   R[13]   R[14]   R[15]  /
   1897      *</pre>
   1898      * @param R current rotation matrix
   1899      * @param prevR previous rotation matrix
   1900      * @param angleChange an array of floats in which the angle change is stored
   1901      */
   1902 
   1903     public static void getAngleChange( float[] angleChange, float[] R, float[] prevR) {
   1904         float rd1=0,rd4=0, rd6=0,rd7=0, rd8=0;
   1905         float ri0=0,ri1=0,ri2=0,ri3=0,ri4=0,ri5=0,ri6=0,ri7=0,ri8=0;
   1906         float pri0=0, pri1=0, pri2=0, pri3=0, pri4=0, pri5=0, pri6=0, pri7=0, pri8=0;
   1907         int i, j, k;
   1908 
   1909         if(R.length == 9) {
   1910             ri0 = R[0];
   1911             ri1 = R[1];
   1912             ri2 = R[2];
   1913             ri3 = R[3];
   1914             ri4 = R[4];
   1915             ri5 = R[5];
   1916             ri6 = R[6];
   1917             ri7 = R[7];
   1918             ri8 = R[8];
   1919         } else if(R.length == 16) {
   1920             ri0 = R[0];
   1921             ri1 = R[1];
   1922             ri2 = R[2];
   1923             ri3 = R[4];
   1924             ri4 = R[5];
   1925             ri5 = R[6];
   1926             ri6 = R[8];
   1927             ri7 = R[9];
   1928             ri8 = R[10];
   1929         }
   1930 
   1931         if(prevR.length == 9) {
   1932             pri0 = prevR[0];
   1933             pri1 = prevR[1];
   1934             pri2 = prevR[2];
   1935             pri3 = prevR[3];
   1936             pri4 = prevR[4];
   1937             pri5 = prevR[5];
   1938             pri6 = prevR[6];
   1939             pri7 = prevR[7];
   1940             pri8 = prevR[8];
   1941         } else if(prevR.length == 16) {
   1942             pri0 = prevR[0];
   1943             pri1 = prevR[1];
   1944             pri2 = prevR[2];
   1945             pri3 = prevR[4];
   1946             pri4 = prevR[5];
   1947             pri5 = prevR[6];
   1948             pri6 = prevR[8];
   1949             pri7 = prevR[9];
   1950             pri8 = prevR[10];
   1951         }
   1952 
   1953         // calculate the parts of the rotation difference matrix we need
   1954         // rd[i][j] = pri[0][i] * ri[0][j] + pri[1][i] * ri[1][j] + pri[2][i] * ri[2][j];
   1955 
   1956         rd1 = pri0 * ri1 + pri3 * ri4 + pri6 * ri7; //rd[0][1]
   1957         rd4 = pri1 * ri1 + pri4 * ri4 + pri7 * ri7; //rd[1][1]
   1958         rd6 = pri2 * ri0 + pri5 * ri3 + pri8 * ri6; //rd[2][0]
   1959         rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1]
   1960         rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2]
   1961 
   1962         angleChange[0] = (float)Math.atan2(rd1, rd4);
   1963         angleChange[1] = (float)Math.asin(-rd7);
   1964         angleChange[2] = (float)Math.atan2(-rd6, rd8);
   1965 
   1966     }
   1967 
   1968     /** Helper function to convert a rotation vector to a rotation matrix.
   1969      *  Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a
   1970      *  9  or 16 element rotation matrix in the array R.  R must have length 9 or 16.
   1971      *  If R.length == 9, the following matrix is returned:
   1972      * <pre>
   1973      *   /  R[ 0]   R[ 1]   R[ 2]   \
   1974      *   |  R[ 3]   R[ 4]   R[ 5]   |
   1975      *   \  R[ 6]   R[ 7]   R[ 8]   /
   1976      *</pre>
   1977      * If R.length == 16, the following matrix is returned:
   1978      * <pre>
   1979      *   /  R[ 0]   R[ 1]   R[ 2]   0  \
   1980      *   |  R[ 4]   R[ 5]   R[ 6]   0  |
   1981      *   |  R[ 8]   R[ 9]   R[10]   0  |
   1982      *   \  0       0       0       1  /
   1983      *</pre>
   1984      *  @param rotationVector the rotation vector to convert
   1985      *  @param R an array of floats in which to store the rotation matrix
   1986      */
   1987     public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) {
   1988 
   1989         float q0;
   1990         float q1 = rotationVector[0];
   1991         float q2 = rotationVector[1];
   1992         float q3 = rotationVector[2];
   1993 
   1994         if (rotationVector.length == 4) {
   1995             q0 = rotationVector[3];
   1996         } else {
   1997             q0 = 1 - q1*q1 - q2*q2 - q3*q3;
   1998             q0 = (q0 > 0) ? (float)Math.sqrt(q0) : 0;
   1999         }
   2000 
   2001         float sq_q1 = 2 * q1 * q1;
   2002         float sq_q2 = 2 * q2 * q2;
   2003         float sq_q3 = 2 * q3 * q3;
   2004         float q1_q2 = 2 * q1 * q2;
   2005         float q3_q0 = 2 * q3 * q0;
   2006         float q1_q3 = 2 * q1 * q3;
   2007         float q2_q0 = 2 * q2 * q0;
   2008         float q2_q3 = 2 * q2 * q3;
   2009         float q1_q0 = 2 * q1 * q0;
   2010 
   2011         if(R.length == 9) {
   2012             R[0] = 1 - sq_q2 - sq_q3;
   2013             R[1] = q1_q2 - q3_q0;
   2014             R[2] = q1_q3 + q2_q0;
   2015 
   2016             R[3] = q1_q2 + q3_q0;
   2017             R[4] = 1 - sq_q1 - sq_q3;
   2018             R[5] = q2_q3 - q1_q0;
   2019 
   2020             R[6] = q1_q3 - q2_q0;
   2021             R[7] = q2_q3 + q1_q0;
   2022             R[8] = 1 - sq_q1 - sq_q2;
   2023         } else if (R.length == 16) {
   2024             R[0] = 1 - sq_q2 - sq_q3;
   2025             R[1] = q1_q2 - q3_q0;
   2026             R[2] = q1_q3 + q2_q0;
   2027             R[3] = 0.0f;
   2028 
   2029             R[4] = q1_q2 + q3_q0;
   2030             R[5] = 1 - sq_q1 - sq_q3;
   2031             R[6] = q2_q3 - q1_q0;
   2032             R[7] = 0.0f;
   2033 
   2034             R[8] = q1_q3 - q2_q0;
   2035             R[9] = q2_q3 + q1_q0;
   2036             R[10] = 1 - sq_q1 - sq_q2;
   2037             R[11] = 0.0f;
   2038 
   2039             R[12] = R[13] = R[14] = 0.0f;
   2040             R[15] = 1.0f;
   2041         }
   2042     }
   2043 
   2044     /** Helper function to convert a rotation vector to a normalized quaternion.
   2045      *  Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a normalized
   2046      *  quaternion in the array Q.  The quaternion is stored as [w, x, y, z]
   2047      *  @param rv the rotation vector to convert
   2048      *  @param Q an array of floats in which to store the computed quaternion
   2049      */
   2050     public static void getQuaternionFromVector(float[] Q, float[] rv) {
   2051         if (rv.length == 4) {
   2052             Q[0] = rv[3];
   2053         } else {
   2054             Q[0] = 1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2];
   2055             Q[0] = (Q[0] > 0) ? (float)Math.sqrt(Q[0]) : 0;
   2056         }
   2057         Q[1] = rv[0];
   2058         Q[2] = rv[1];
   2059         Q[3] = rv[2];
   2060     }
   2061 
   2062     private static native void nativeClassInit();
   2063 
   2064     private static native int sensors_module_init();
   2065     private static native int sensors_module_get_next_sensor(Sensor sensor, int next);
   2066 
   2067     // Used within this module from outside SensorManager, don't make private
   2068     static native int sensors_create_queue();
   2069     static native void sensors_destroy_queue(int queue);
   2070     static native boolean sensors_enable_sensor(int queue, String name, int sensor, int enable);
   2071     static native int sensors_data_poll(int queue, float[] values, int[] status, long[] timestamp);
   2072 }
   2073