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.Handler;
     20 import android.util.Log;
     21 import android.util.SparseArray;
     22 
     23 import java.util.ArrayList;
     24 import java.util.Collections;
     25 import java.util.List;
     26 
     27 /**
     28  * <p>
     29  * SensorManager lets you access the device's {@link android.hardware.Sensor
     30  * sensors}. Get an instance of this class by calling
     31  * {@link android.content.Context#getSystemService(java.lang.String)
     32  * Context.getSystemService()} with the argument
     33  * {@link android.content.Context#SENSOR_SERVICE}.
     34  * </p>
     35  * <p>
     36  * Always make sure to disable sensors you don't need, especially when your
     37  * activity is paused. Failing to do so can drain the battery in just a few
     38  * hours. Note that the system will <i>not</i> disable sensors automatically when
     39  * the screen turns off.
     40  * </p>
     41  *
     42  * <pre class="prettyprint">
     43  * public class SensorActivity extends Activity, implements SensorEventListener {
     44  *     private final SensorManager mSensorManager;
     45  *     private final Sensor mAccelerometer;
     46  *
     47  *     public SensorActivity() {
     48  *         mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
     49  *         mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
     50  *     }
     51  *
     52  *     protected void onResume() {
     53  *         super.onResume();
     54  *         mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
     55  *     }
     56  *
     57  *     protected void onPause() {
     58  *         super.onPause();
     59  *         mSensorManager.unregisterListener(this);
     60  *     }
     61  *
     62  *     public void onAccuracyChanged(Sensor sensor, int accuracy) {
     63  *     }
     64  *
     65  *     public void onSensorChanged(SensorEvent event) {
     66  *     }
     67  * }
     68  * </pre>
     69  *
     70  * @see SensorEventListener
     71  * @see SensorEvent
     72  * @see Sensor
     73  *
     74  */
     75 public abstract class SensorManager {
     76     /** @hide */
     77     protected static final String TAG = "SensorManager";
     78 
     79     private static final float[] mTempMatrix = new float[16];
     80 
     81     // Cached lists of sensors by type.  Guarded by mSensorListByType.
     82     private final SparseArray<List<Sensor>> mSensorListByType =
     83             new SparseArray<List<Sensor>>();
     84 
     85     // Legacy sensor manager implementation.  Guarded by mSensorListByType during initialization.
     86     private LegacySensorManager mLegacySensorManager;
     87 
     88     /* NOTE: sensor IDs must be a power of 2 */
     89 
     90     /**
     91      * A constant describing an orientation sensor. See
     92      * {@link android.hardware.SensorListener SensorListener} for more details.
     93      *
     94      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
     95      */
     96     @Deprecated
     97     public static final int SENSOR_ORIENTATION = 1 << 0;
     98 
     99     /**
    100      * A constant describing an accelerometer. See
    101      * {@link android.hardware.SensorListener SensorListener} for more details.
    102      *
    103      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    104      */
    105     @Deprecated
    106     public static final int SENSOR_ACCELEROMETER = 1 << 1;
    107 
    108     /**
    109      * A constant describing a temperature sensor See
    110      * {@link android.hardware.SensorListener SensorListener} for more details.
    111      *
    112      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    113      */
    114     @Deprecated
    115     public static final int SENSOR_TEMPERATURE = 1 << 2;
    116 
    117     /**
    118      * A constant describing a magnetic sensor See
    119      * {@link android.hardware.SensorListener SensorListener} for more details.
    120      *
    121      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    122      */
    123     @Deprecated
    124     public static final int SENSOR_MAGNETIC_FIELD = 1 << 3;
    125 
    126     /**
    127      * A constant describing an ambient light sensor See
    128      * {@link android.hardware.SensorListener SensorListener} for more details.
    129      *
    130      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    131      */
    132     @Deprecated
    133     public static final int SENSOR_LIGHT = 1 << 4;
    134 
    135     /**
    136      * A constant describing a proximity sensor See
    137      * {@link android.hardware.SensorListener SensorListener} for more details.
    138      *
    139      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    140      */
    141     @Deprecated
    142     public static final int SENSOR_PROXIMITY = 1 << 5;
    143 
    144     /**
    145      * A constant describing a Tricorder See
    146      * {@link android.hardware.SensorListener SensorListener} for more details.
    147      *
    148      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    149      */
    150     @Deprecated
    151     public static final int SENSOR_TRICORDER = 1 << 6;
    152 
    153     /**
    154      * A constant describing an orientation sensor. See
    155      * {@link android.hardware.SensorListener SensorListener} for more details.
    156      *
    157      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    158      */
    159     @Deprecated
    160     public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
    161 
    162     /**
    163      * A constant that includes all sensors
    164      *
    165      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    166      */
    167     @Deprecated
    168     public static final int SENSOR_ALL = 0x7F;
    169 
    170     /**
    171      * Smallest sensor ID
    172      *
    173      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    174      */
    175     @Deprecated
    176     public static final int SENSOR_MIN = SENSOR_ORIENTATION;
    177 
    178     /**
    179      * Largest sensor ID
    180      *
    181      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    182      */
    183     @Deprecated
    184     public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1);
    185 
    186 
    187     /**
    188      * Index of the X value in the array returned by
    189      * {@link android.hardware.SensorListener#onSensorChanged}
    190      *
    191      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    192      */
    193     @Deprecated
    194     public static final int DATA_X = 0;
    195 
    196     /**
    197      * Index of the Y value in the array returned by
    198      * {@link android.hardware.SensorListener#onSensorChanged}
    199      *
    200      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    201      */
    202     @Deprecated
    203     public static final int DATA_Y = 1;
    204 
    205     /**
    206      * Index of the Z value in the array returned by
    207      * {@link android.hardware.SensorListener#onSensorChanged}
    208      *
    209      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    210      */
    211     @Deprecated
    212     public static final int DATA_Z = 2;
    213 
    214     /**
    215      * Offset to the untransformed values in the array returned by
    216      * {@link android.hardware.SensorListener#onSensorChanged}
    217      *
    218      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    219      */
    220     @Deprecated
    221     public static final int RAW_DATA_INDEX = 3;
    222 
    223     /**
    224      * Index of the untransformed X value in the array returned by
    225      * {@link android.hardware.SensorListener#onSensorChanged}
    226      *
    227      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    228      */
    229     @Deprecated
    230     public static final int RAW_DATA_X = 3;
    231 
    232     /**
    233      * Index of the untransformed Y value in the array returned by
    234      * {@link android.hardware.SensorListener#onSensorChanged}
    235      *
    236      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    237      */
    238     @Deprecated
    239     public static final int RAW_DATA_Y = 4;
    240 
    241     /**
    242      * Index of the untransformed Z value in the array returned by
    243      * {@link android.hardware.SensorListener#onSensorChanged}
    244      *
    245      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
    246      */
    247     @Deprecated
    248     public static final int RAW_DATA_Z = 5;
    249 
    250     /** Standard gravity (g) on Earth. This value is equivalent to 1G */
    251     public static final float STANDARD_GRAVITY = 9.80665f;
    252 
    253     /** Sun's gravity in SI units (m/s^2) */
    254     public static final float GRAVITY_SUN             = 275.0f;
    255     /** Mercury's gravity in SI units (m/s^2) */
    256     public static final float GRAVITY_MERCURY         = 3.70f;
    257     /** Venus' gravity in SI units (m/s^2) */
    258     public static final float GRAVITY_VENUS           = 8.87f;
    259     /** Earth's gravity in SI units (m/s^2) */
    260     public static final float GRAVITY_EARTH           = 9.80665f;
    261     /** The Moon's gravity in SI units (m/s^2) */
    262     public static final float GRAVITY_MOON            = 1.6f;
    263     /** Mars' gravity in SI units (m/s^2) */
    264     public static final float GRAVITY_MARS            = 3.71f;
    265     /** Jupiter's gravity in SI units (m/s^2) */
    266     public static final float GRAVITY_JUPITER         = 23.12f;
    267     /** Saturn's gravity in SI units (m/s^2) */
    268     public static final float GRAVITY_SATURN          = 8.96f;
    269     /** Uranus' gravity in SI units (m/s^2) */
    270     public static final float GRAVITY_URANUS          = 8.69f;
    271     /** Neptune's gravity in SI units (m/s^2) */
    272     public static final float GRAVITY_NEPTUNE         = 11.0f;
    273     /** Pluto's gravity in SI units (m/s^2) */
    274     public static final float GRAVITY_PLUTO           = 0.6f;
    275     /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */
    276     public static final float GRAVITY_DEATH_STAR_I    = 0.000000353036145f;
    277     /** Gravity on the island */
    278     public static final float GRAVITY_THE_ISLAND      = 4.815162342f;
    279 
    280 
    281     /** Maximum magnetic field on Earth's surface */
    282     public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f;
    283     /** Minimum magnetic field on Earth's surface */
    284     public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;
    285 
    286 
    287     /** Standard atmosphere, or average sea-level pressure in hPa (millibar) */
    288     public static final float PRESSURE_STANDARD_ATMOSPHERE = 1013.25f;
    289 
    290 
    291     /** Maximum luminance of sunlight in lux */
    292     public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
    293     /** luminance of sunlight in lux */
    294     public static final float LIGHT_SUNLIGHT     = 110000.0f;
    295     /** luminance in shade in lux */
    296     public static final float LIGHT_SHADE        = 20000.0f;
    297     /** luminance under an overcast sky in lux */
    298     public static final float LIGHT_OVERCAST     = 10000.0f;
    299     /** luminance at sunrise in lux */
    300     public static final float LIGHT_SUNRISE      = 400.0f;
    301     /** luminance under a cloudy sky in lux */
    302     public static final float LIGHT_CLOUDY       = 100.0f;
    303     /** luminance at night with full moon in lux */
    304     public static final float LIGHT_FULLMOON     = 0.25f;
    305     /** luminance at night with no moon in lux*/
    306     public static final float LIGHT_NO_MOON      = 0.001f;
    307 
    308 
    309     /** get sensor data as fast as possible */
    310     public static final int SENSOR_DELAY_FASTEST = 0;
    311     /** rate suitable for games */
    312     public static final int SENSOR_DELAY_GAME = 1;
    313     /** rate suitable for the user interface  */
    314     public static final int SENSOR_DELAY_UI = 2;
    315     /** rate (default) suitable for screen orientation changes */
    316     public static final int SENSOR_DELAY_NORMAL = 3;
    317 
    318 
    319     /**
    320      * The values returned by this sensor cannot be trusted, calibration is
    321      * needed or the environment doesn't allow readings
    322      */
    323     public static final int SENSOR_STATUS_UNRELIABLE = 0;
    324 
    325     /**
    326      * This sensor is reporting data with low accuracy, calibration with the
    327      * environment is needed
    328      */
    329     public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
    330 
    331     /**
    332      * This sensor is reporting data with an average level of accuracy,
    333      * calibration with the environment may improve the readings
    334      */
    335     public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;
    336 
    337     /** This sensor is reporting data with maximum accuracy */
    338     public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;
    339 
    340     /** see {@link #remapCoordinateSystem} */
    341     public static final int AXIS_X = 1;
    342     /** see {@link #remapCoordinateSystem} */
    343     public static final int AXIS_Y = 2;
    344     /** see {@link #remapCoordinateSystem} */
    345     public static final int AXIS_Z = 3;
    346     /** see {@link #remapCoordinateSystem} */
    347     public static final int AXIS_MINUS_X = AXIS_X | 0x80;
    348     /** see {@link #remapCoordinateSystem} */
    349     public static final int AXIS_MINUS_Y = AXIS_Y | 0x80;
    350     /** see {@link #remapCoordinateSystem} */
    351     public static final int AXIS_MINUS_Z = AXIS_Z | 0x80;
    352 
    353 
    354     /**
    355      * {@hide}
    356      */
    357     public SensorManager() {
    358     }
    359 
    360     /**
    361      * Gets the full list of sensors that are available.
    362      * @hide
    363      */
    364     protected abstract List<Sensor> getFullSensorList();
    365 
    366     /**
    367      * @return available sensors.
    368      * @deprecated This method is deprecated, use
    369      *             {@link SensorManager#getSensorList(int)} instead
    370      */
    371     @Deprecated
    372     public int getSensors() {
    373         return getLegacySensorManager().getSensors();
    374     }
    375 
    376     /**
    377      * Use this method to get the list of available sensors of a certain type.
    378      * Make multiple calls to get sensors of different types or use
    379      * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the
    380      * sensors.
    381      *
    382      * @param type
    383      *        of sensors requested
    384      *
    385      * @return a list of sensors matching the asked type.
    386      *
    387      * @see #getDefaultSensor(int)
    388      * @see Sensor
    389      */
    390     public List<Sensor> getSensorList(int type) {
    391         // cache the returned lists the first time
    392         List<Sensor> list;
    393         final List<Sensor> fullList = getFullSensorList();
    394         synchronized (mSensorListByType) {
    395             list = mSensorListByType.get(type);
    396             if (list == null) {
    397                 if (type == Sensor.TYPE_ALL) {
    398                     list = fullList;
    399                 } else {
    400                     list = new ArrayList<Sensor>();
    401                     for (Sensor i : fullList) {
    402                         if (i.getType() == type)
    403                             list.add(i);
    404                     }
    405                 }
    406                 list = Collections.unmodifiableList(list);
    407                 mSensorListByType.append(type, list);
    408             }
    409         }
    410         return list;
    411     }
    412 
    413     /**
    414      * Use this method to get the default sensor for a given type. Note that the
    415      * returned sensor could be a composite sensor, and its data could be
    416      * averaged or filtered. If you need to access the raw sensors use
    417      * {@link SensorManager#getSensorList(int) getSensorList}.
    418      *
    419      * @param type
    420      *        of sensors requested
    421      *
    422      * @return the default sensors matching the asked type.
    423      *
    424      * @see #getSensorList(int)
    425      * @see Sensor
    426      */
    427     public Sensor getDefaultSensor(int type) {
    428         // TODO: need to be smarter, for now, just return the 1st sensor
    429         List<Sensor> l = getSensorList(type);
    430         return l.isEmpty() ? null : l.get(0);
    431     }
    432 
    433     /**
    434      * Registers a listener for given sensors.
    435      *
    436      * @deprecated This method is deprecated, use
    437      *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
    438      *             instead.
    439      *
    440      * @param listener
    441      *        sensor listener object
    442      *
    443      * @param sensors
    444      *        a bit masks of the sensors to register to
    445      *
    446      * @return <code>true</code> if the sensor is supported and successfully
    447      *         enabled
    448      */
    449     @Deprecated
    450     public boolean registerListener(SensorListener listener, int sensors) {
    451         return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
    452     }
    453 
    454     /**
    455      * Registers a SensorListener for given sensors.
    456      *
    457      * @deprecated This method is deprecated, use
    458      *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
    459      *             instead.
    460      *
    461      * @param listener
    462      *        sensor listener object
    463      *
    464      * @param sensors
    465      *        a bit masks of the sensors to register to
    466      *
    467      * @param rate
    468      *        rate of events. This is only a hint to the system. events may be
    469      *        received faster or slower than the specified rate. Usually events
    470      *        are received faster. The value must be one of
    471      *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
    472      *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
    473      *
    474      * @return <code>true</code> if the sensor is supported and successfully
    475      *         enabled
    476      */
    477     @Deprecated
    478     public boolean registerListener(SensorListener listener, int sensors, int rate) {
    479         return getLegacySensorManager().registerListener(listener, sensors, rate);
    480     }
    481 
    482     /**
    483      * Unregisters a listener for all sensors.
    484      *
    485      * @deprecated This method is deprecated, use
    486      *             {@link SensorManager#unregisterListener(SensorEventListener)}
    487      *             instead.
    488      *
    489      * @param listener
    490      *        a SensorListener object
    491      */
    492     @Deprecated
    493     public void unregisterListener(SensorListener listener) {
    494         unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
    495     }
    496 
    497     /**
    498      * Unregisters a listener for the sensors with which it is registered.
    499      *
    500      * @deprecated This method is deprecated, use
    501      *             {@link SensorManager#unregisterListener(SensorEventListener, Sensor)}
    502      *             instead.
    503      *
    504      * @param listener
    505      *        a SensorListener object
    506      *
    507      * @param sensors
    508      *        a bit masks of the sensors to unregister from
    509      */
    510     @Deprecated
    511     public void unregisterListener(SensorListener listener, int sensors) {
    512         getLegacySensorManager().unregisterListener(listener, sensors);
    513     }
    514 
    515     /**
    516      * Unregisters a listener for the sensors with which it is registered.
    517      *
    518      * @param listener
    519      *        a SensorEventListener object
    520      *
    521      * @param sensor
    522      *        the sensor to unregister from
    523      *
    524      * @see #unregisterListener(SensorEventListener)
    525      * @see #registerListener(SensorEventListener, Sensor, int)
    526      *
    527      */
    528     public void unregisterListener(SensorEventListener listener, Sensor sensor) {
    529         if (listener == null || sensor == null) {
    530             return;
    531         }
    532 
    533         unregisterListenerImpl(listener, sensor);
    534     }
    535 
    536     /**
    537      * Unregisters a listener for all sensors.
    538      *
    539      * @param listener
    540      *        a SensorListener object
    541      *
    542      * @see #unregisterListener(SensorEventListener, Sensor)
    543      * @see #registerListener(SensorEventListener, Sensor, int)
    544      *
    545      */
    546     public void unregisterListener(SensorEventListener listener) {
    547         if (listener == null) {
    548             return;
    549         }
    550 
    551         unregisterListenerImpl(listener, null);
    552     }
    553 
    554     /** @hide */
    555     protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor sensor);
    556 
    557     /**
    558      * Registers a {@link android.hardware.SensorEventListener
    559      * SensorEventListener} for the given sensor.
    560      *
    561      * @param listener
    562      *        A {@link android.hardware.SensorEventListener SensorEventListener}
    563      *        object.
    564      *
    565      * @param sensor
    566      *        The {@link android.hardware.Sensor Sensor} to register to.
    567      *
    568      * @param rate
    569      *        The rate {@link android.hardware.SensorEvent sensor events} are
    570      *        delivered at. This is only a hint to the system. Events may be
    571      *        received faster or slower than the specified rate. Usually events
    572      *        are received faster. The value must be one of
    573      *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
    574      *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}
    575      *        or, the desired delay between events in microsecond.
    576      *
    577      * @return <code>true</code> if the sensor is supported and successfully
    578      *         enabled.
    579      *
    580      * @see #registerListener(SensorEventListener, Sensor, int, Handler)
    581      * @see #unregisterListener(SensorEventListener)
    582      * @see #unregisterListener(SensorEventListener, Sensor)
    583      *
    584      */
    585     public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {
    586         return registerListener(listener, sensor, rate, null);
    587     }
    588 
    589     /**
    590      * Registers a {@link android.hardware.SensorEventListener
    591      * SensorEventListener} for the given sensor.
    592      *
    593      * @param listener
    594      *        A {@link android.hardware.SensorEventListener SensorEventListener}
    595      *        object.
    596      *
    597      * @param sensor
    598      *        The {@link android.hardware.Sensor Sensor} to register to.
    599      *
    600      * @param rate
    601      *        The rate {@link android.hardware.SensorEvent sensor events} are
    602      *        delivered at. This is only a hint to the system. Events may be
    603      *        received faster or slower than the specified rate. Usually events
    604      *        are received faster. The value must be one of
    605      *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
    606      *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
    607      *        or, the desired delay between events in microsecond.
    608      *
    609      * @param handler
    610      *        The {@link android.os.Handler Handler} the
    611      *        {@link android.hardware.SensorEvent sensor events} will be
    612      *        delivered to.
    613      *
    614      * @return true if the sensor is supported and successfully enabled.
    615      *
    616      * @see #registerListener(SensorEventListener, Sensor, int)
    617      * @see #unregisterListener(SensorEventListener)
    618      * @see #unregisterListener(SensorEventListener, Sensor)
    619      *
    620      */
    621     public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,
    622             Handler handler) {
    623         if (listener == null || sensor == null) {
    624             return false;
    625         }
    626 
    627         int delay = -1;
    628         switch (rate) {
    629             case SENSOR_DELAY_FASTEST:
    630                 delay = 0;
    631                 break;
    632             case SENSOR_DELAY_GAME:
    633                 delay = 20000;
    634                 break;
    635             case SENSOR_DELAY_UI:
    636                 delay = 66667;
    637                 break;
    638             case SENSOR_DELAY_NORMAL:
    639                 delay = 200000;
    640                 break;
    641             default:
    642                 delay = rate;
    643                 break;
    644         }
    645 
    646         return registerListenerImpl(listener, sensor, delay, handler);
    647     }
    648 
    649     /** @hide */
    650     protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
    651             int delay, Handler handler);
    652 
    653     /**
    654      * <p>
    655      * Computes the inclination matrix <b>I</b> as well as the rotation matrix
    656      * <b>R</b> transforming a vector from the device coordinate system to the
    657      * world's coordinate system which is defined as a direct orthonormal basis,
    658      * where:
    659      * </p>
    660      *
    661      * <ul>
    662      * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
    663      * the ground at the device's current location and roughly points East).</li>
    664      * <li>Y is tangential to the ground at the device's current location and
    665      * points towards the magnetic North Pole.</li>
    666      * <li>Z points towards the sky and is perpendicular to the ground.</li>
    667      * </ul>
    668      *
    669      * <p>
    670      * <center><img src="../../../images/axis_globe.png"
    671      * alt="World coordinate-system diagram." border="0" /></center>
    672      * </p>
    673      *
    674      * <p>
    675      * <hr>
    676      * <p>
    677      * By definition:
    678      * <p>
    679      * [0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity)
    680      * <p>
    681      * [0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b> (m = magnitude of
    682      * geomagnetic field)
    683      * <p>
    684      * <b>R</b> is the identity matrix when the device is aligned with the
    685      * world's coordinate system, that is, when the device's X axis points
    686      * toward East, the Y axis points to the North Pole and the device is facing
    687      * the sky.
    688      *
    689      * <p>
    690      * <b>I</b> is a rotation matrix transforming the geomagnetic vector into
    691      * the same coordinate space as gravity (the world's coordinate space).
    692      * <b>I</b> is a simple rotation around the X axis. The inclination angle in
    693      * radians can be computed with {@link #getInclination}.
    694      * <hr>
    695      *
    696      * <p>
    697      * Each matrix is returned either as a 3x3 or 4x4 row-major matrix depending
    698      * on the length of the passed array:
    699      * <p>
    700      * <u>If the array length is 16:</u>
    701      *
    702      * <pre>
    703      *   /  M[ 0]   M[ 1]   M[ 2]   M[ 3]  \
    704      *   |  M[ 4]   M[ 5]   M[ 6]   M[ 7]  |
    705      *   |  M[ 8]   M[ 9]   M[10]   M[11]  |
    706      *   \  M[12]   M[13]   M[14]   M[15]  /
    707      *</pre>
    708      *
    709      * This matrix is ready to be used by OpenGL ES's
    710      * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int)
    711      * glLoadMatrixf(float[], int)}.
    712      * <p>
    713      * Note that because OpenGL matrices are column-major matrices you must
    714      * transpose the matrix before using it. However, since the matrix is a
    715      * rotation matrix, its transpose is also its inverse, conveniently, it is
    716      * often the inverse of the rotation that is needed for rendering; it can
    717      * therefore be used with OpenGL ES directly.
    718      * <p>
    719      * Also note that the returned matrices always have this form:
    720      *
    721      * <pre>
    722      *   /  M[ 0]   M[ 1]   M[ 2]   0  \
    723      *   |  M[ 4]   M[ 5]   M[ 6]   0  |
    724      *   |  M[ 8]   M[ 9]   M[10]   0  |
    725      *   \      0       0       0   1  /
    726      *</pre>
    727      *
    728      * <p>
    729      * <u>If the array length is 9:</u>
    730      *
    731      * <pre>
    732      *   /  M[ 0]   M[ 1]   M[ 2]  \
    733      *   |  M[ 3]   M[ 4]   M[ 5]  |
    734      *   \  M[ 6]   M[ 7]   M[ 8]  /
    735      *</pre>
    736      *
    737      * <hr>
    738      * <p>
    739      * The inverse of each matrix can be computed easily by taking its
    740      * transpose.
    741      *
    742      * <p>
    743      * The matrices returned by this function are meaningful only when the
    744      * device is not free-falling and it is not close to the magnetic north. If
    745      * the device is accelerating, or placed into a strong magnetic field, the
    746      * returned matrices may be inaccurate.
    747      *
    748      * @param R
    749      *        is an array of 9 floats holding the rotation matrix <b>R</b> when
    750      *        this function returns. R can be null.
    751      *        <p>
    752      *
    753      * @param I
    754      *        is an array of 9 floats holding the rotation matrix <b>I</b> when
    755      *        this function returns. I can be null.
    756      *        <p>
    757      *
    758      * @param gravity
    759      *        is an array of 3 floats containing the gravity vector expressed in
    760      *        the device's coordinate. You can simply use the
    761      *        {@link android.hardware.SensorEvent#values values} returned by a
    762      *        {@link android.hardware.SensorEvent SensorEvent} of a
    763      *        {@link android.hardware.Sensor Sensor} of type
    764      *        {@link android.hardware.Sensor#TYPE_ACCELEROMETER
    765      *        TYPE_ACCELEROMETER}.
    766      *        <p>
    767      *
    768      * @param geomagnetic
    769      *        is an array of 3 floats containing the geomagnetic vector
    770      *        expressed in the device's coordinate. You can simply use the
    771      *        {@link android.hardware.SensorEvent#values values} returned by a
    772      *        {@link android.hardware.SensorEvent SensorEvent} of a
    773      *        {@link android.hardware.Sensor Sensor} of type
    774      *        {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD
    775      *        TYPE_MAGNETIC_FIELD}.
    776      *
    777      * @return <code>true</code> on success, <code>false</code> on failure (for
    778      *         instance, if the device is in free fall). On failure the output
    779      *         matrices are not modified.
    780      *
    781      * @see #getInclination(float[])
    782      * @see #getOrientation(float[], float[])
    783      * @see #remapCoordinateSystem(float[], int, int, float[])
    784      */
    785 
    786     public static boolean getRotationMatrix(float[] R, float[] I,
    787             float[] gravity, float[] geomagnetic) {
    788         // TODO: move this to native code for efficiency
    789         float Ax = gravity[0];
    790         float Ay = gravity[1];
    791         float Az = gravity[2];
    792         final float Ex = geomagnetic[0];
    793         final float Ey = geomagnetic[1];
    794         final float Ez = geomagnetic[2];
    795         float Hx = Ey*Az - Ez*Ay;
    796         float Hy = Ez*Ax - Ex*Az;
    797         float Hz = Ex*Ay - Ey*Ax;
    798         final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
    799         if (normH < 0.1f) {
    800             // device is close to free fall (or in space?), or close to
    801             // magnetic north pole. Typical values are  > 100.
    802             return false;
    803         }
    804         final float invH = 1.0f / normH;
    805         Hx *= invH;
    806         Hy *= invH;
    807         Hz *= invH;
    808         final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
    809         Ax *= invA;
    810         Ay *= invA;
    811         Az *= invA;
    812         final float Mx = Ay*Hz - Az*Hy;
    813         final float My = Az*Hx - Ax*Hz;
    814         final float Mz = Ax*Hy - Ay*Hx;
    815         if (R != null) {
    816             if (R.length == 9) {
    817                 R[0] = Hx;     R[1] = Hy;     R[2] = Hz;
    818                 R[3] = Mx;     R[4] = My;     R[5] = Mz;
    819                 R[6] = Ax;     R[7] = Ay;     R[8] = Az;
    820             } else if (R.length == 16) {
    821                 R[0]  = Hx;    R[1]  = Hy;    R[2]  = Hz;   R[3]  = 0;
    822                 R[4]  = Mx;    R[5]  = My;    R[6]  = Mz;   R[7]  = 0;
    823                 R[8]  = Ax;    R[9]  = Ay;    R[10] = Az;   R[11] = 0;
    824                 R[12] = 0;     R[13] = 0;     R[14] = 0;    R[15] = 1;
    825             }
    826         }
    827         if (I != null) {
    828             // compute the inclination matrix by projecting the geomagnetic
    829             // vector onto the Z (gravity) and X (horizontal component
    830             // of geomagnetic vector) axes.
    831             final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
    832             final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
    833             final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
    834             if (I.length == 9) {
    835                 I[0] = 1;     I[1] = 0;     I[2] = 0;
    836                 I[3] = 0;     I[4] = c;     I[5] = s;
    837                 I[6] = 0;     I[7] =-s;     I[8] = c;
    838             } else if (I.length == 16) {
    839                 I[0] = 1;     I[1] = 0;     I[2] = 0;
    840                 I[4] = 0;     I[5] = c;     I[6] = s;
    841                 I[8] = 0;     I[9] =-s;     I[10]= c;
    842                 I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
    843                 I[15] = 1;
    844             }
    845         }
    846         return true;
    847     }
    848 
    849     /**
    850      * Computes the geomagnetic inclination angle in radians from the
    851      * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}.
    852      *
    853      * @param I
    854      *        inclination matrix see {@link #getRotationMatrix}.
    855      *
    856      * @return The geomagnetic inclination angle in radians.
    857      *
    858      * @see #getRotationMatrix(float[], float[], float[], float[])
    859      * @see #getOrientation(float[], float[])
    860      * @see GeomagneticField
    861      *
    862      */
    863     public static float getInclination(float[] I) {
    864         if (I.length == 9) {
    865             return (float)Math.atan2(I[5], I[4]);
    866         } else {
    867             return (float)Math.atan2(I[6], I[5]);
    868         }
    869     }
    870 
    871     /**
    872      * <p>
    873      * Rotates the supplied rotation matrix so it is expressed in a different
    874      * coordinate system. This is typically used when an application needs to
    875      * compute the three orientation angles of the device (see
    876      * {@link #getOrientation}) in a different coordinate system.
    877      * </p>
    878      *
    879      * <p>
    880      * When the rotation matrix is used for drawing (for instance with OpenGL
    881      * ES), it usually <b>doesn't need</b> to be transformed by this function,
    882      * unless the screen is physically rotated, in which case you can use
    883      * {@link android.view.Display#getRotation() Display.getRotation()} to
    884      * retrieve the current rotation of the screen. Note that because the user
    885      * is generally free to rotate their screen, you often should consider the
    886      * rotation in deciding the parameters to use here.
    887      * </p>
    888      *
    889      * <p>
    890      * <u>Examples:</u>
    891      * <p>
    892      *
    893      * <ul>
    894      * <li>Using the camera (Y axis along the camera's axis) for an augmented
    895      * reality application where the rotation angles are needed:</li>
    896      *
    897      * <p>
    898      * <ul>
    899      * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code>
    900      * </ul>
    901      * </p>
    902      *
    903      * <li>Using the device as a mechanical compass when rotation is
    904      * {@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:</li>
    905      *
    906      * <p>
    907      * <ul>
    908      * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code>
    909      * </ul>
    910      * </p>
    911      *
    912      * Beware of the above example. This call is needed only to account for a
    913      * rotation from its natural orientation when calculating the rotation
    914      * angles (see {@link #getOrientation}). If the rotation matrix is also used
    915      * for rendering, it may not need to be transformed, for instance if your
    916      * {@link android.app.Activity Activity} is running in landscape mode.
    917      * </ul>
    918      *
    919      * <p>
    920      * Since the resulting coordinate system is orthonormal, only two axes need
    921      * to be specified.
    922      *
    923      * @param inR
    924      *        the rotation matrix to be transformed. Usually it is the matrix
    925      *        returned by {@link #getRotationMatrix}.
    926      *
    927      * @param X
    928      *        defines on which world axis and direction the X axis of the device
    929      *        is mapped.
    930      *
    931      * @param Y
    932      *        defines on which world axis and direction the Y axis of the device
    933      *        is mapped.
    934      *
    935      * @param outR
    936      *        the transformed rotation matrix. inR and outR can be the same
    937      *        array, but it is not recommended for performance reason.
    938      *
    939      * @return <code>true</code> on success. <code>false</code> if the input
    940      *         parameters are incorrect, for instance if X and Y define the same
    941      *         axis. Or if inR and outR don't have the same length.
    942      *
    943      * @see #getRotationMatrix(float[], float[], float[], float[])
    944      */
    945 
    946     public static boolean remapCoordinateSystem(float[] inR, int X, int Y,
    947             float[] outR)
    948     {
    949         if (inR == outR) {
    950             final float[] temp = mTempMatrix;
    951             synchronized(temp) {
    952                 // we don't expect to have a lot of contention
    953                 if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
    954                     final int size = outR.length;
    955                     for (int i=0 ; i<size ; i++)
    956                         outR[i] = temp[i];
    957                     return true;
    958                 }
    959             }
    960         }
    961         return remapCoordinateSystemImpl(inR, X, Y, outR);
    962     }
    963 
    964     private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y,
    965             float[] outR)
    966     {
    967         /*
    968          * X and Y define a rotation matrix 'r':
    969          *
    970          *  (X==1)?((X&0x80)?-1:1):0    (X==2)?((X&0x80)?-1:1):0    (X==3)?((X&0x80)?-1:1):0
    971          *  (Y==1)?((Y&0x80)?-1:1):0    (Y==2)?((Y&0x80)?-1:1):0    (Y==3)?((X&0x80)?-1:1):0
    972          *                              r[0] ^ r[1]
    973          *
    974          * where the 3rd line is the vector product of the first 2 lines
    975          *
    976          */
    977 
    978         final int length = outR.length;
    979         if (inR.length != length)
    980             return false;   // invalid parameter
    981         if ((X & 0x7C)!=0 || (Y & 0x7C)!=0)
    982             return false;   // invalid parameter
    983         if (((X & 0x3)==0) || ((Y & 0x3)==0))
    984             return false;   // no axis specified
    985         if ((X & 0x3) == (Y & 0x3))
    986             return false;   // same axis specified
    987 
    988         // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
    989         // this can be calculated by exclusive-or'ing X and Y; except for
    990         // the sign inversion (+/-) which is calculated below.
    991         int Z = X ^ Y;
    992 
    993         // extract the axis (remove the sign), offset in the range 0 to 2.
    994         final int x = (X & 0x3)-1;
    995         final int y = (Y & 0x3)-1;
    996         final int z = (Z & 0x3)-1;
    997 
    998         // compute the sign of Z (whether it needs to be inverted)
    999         final int axis_y = (z+1)%3;
   1000         final int axis_z = (z+2)%3;
   1001         if (((x^axis_y)|(y^axis_z)) != 0)
   1002             Z ^= 0x80;
   1003 
   1004         final boolean sx = (X>=0x80);
   1005         final boolean sy = (Y>=0x80);
   1006         final boolean sz = (Z>=0x80);
   1007 
   1008         // Perform R * r, in avoiding actual muls and adds.
   1009         final int rowLength = ((length==16)?4:3);
   1010         for (int j=0 ; j<3 ; j++) {
   1011             final int offset = j*rowLength;
   1012             for (int i=0 ; i<3 ; i++) {
   1013                 if (x==i)   outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0];
   1014                 if (y==i)   outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1];
   1015                 if (z==i)   outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2];
   1016             }
   1017         }
   1018         if (length == 16) {
   1019             outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
   1020             outR[15] = 1;
   1021         }
   1022         return true;
   1023     }
   1024 
   1025     /**
   1026      * Computes the device's orientation based on the rotation matrix.
   1027      * <p>
   1028      * When it returns, the array values is filled with the result:
   1029      * <ul>
   1030      * <li>values[0]: <i>azimuth</i>, rotation around the Z axis.</li>
   1031      * <li>values[1]: <i>pitch</i>, rotation around the X axis.</li>
   1032      * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li>
   1033      * </ul>
   1034      * <p>The reference coordinate-system used is different from the world
   1035      * coordinate-system defined for the rotation matrix:</p>
   1036      * <ul>
   1037      * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
   1038      * the ground at the device's current location and roughly points West).</li>
   1039      * <li>Y is tangential to the ground at the device's current location and
   1040      * points towards the magnetic North Pole.</li>
   1041      * <li>Z points towards the center of the Earth and is perpendicular to the ground.</li>
   1042      * </ul>
   1043      *
   1044      * <p>
   1045      * <center><img src="../../../images/axis_globe_inverted.png"
   1046      * alt="Inverted world coordinate-system diagram." border="0" /></center>
   1047      * </p>
   1048      * <p>
   1049      * All three angles above are in <b>radians</b> and <b>positive</b> in the
   1050      * <b>counter-clockwise</b> direction.
   1051      *
   1052      * @param R
   1053      *        rotation matrix see {@link #getRotationMatrix}.
   1054      *
   1055      * @param values
   1056      *        an array of 3 floats to hold the result.
   1057      *
   1058      * @return The array values passed as argument.
   1059      *
   1060      * @see #getRotationMatrix(float[], float[], float[], float[])
   1061      * @see GeomagneticField
   1062      */
   1063     public static float[] getOrientation(float[] R, float values[]) {
   1064         /*
   1065          * 4x4 (length=16) case:
   1066          *   /  R[ 0]   R[ 1]   R[ 2]   0  \
   1067          *   |  R[ 4]   R[ 5]   R[ 6]   0  |
   1068          *   |  R[ 8]   R[ 9]   R[10]   0  |
   1069          *   \      0       0       0   1  /
   1070          *
   1071          * 3x3 (length=9) case:
   1072          *   /  R[ 0]   R[ 1]   R[ 2]  \
   1073          *   |  R[ 3]   R[ 4]   R[ 5]  |
   1074          *   \  R[ 6]   R[ 7]   R[ 8]  /
   1075          *
   1076          */
   1077         if (R.length == 9) {
   1078             values[0] = (float)Math.atan2(R[1], R[4]);
   1079             values[1] = (float)Math.asin(-R[7]);
   1080             values[2] = (float)Math.atan2(-R[6], R[8]);
   1081         } else {
   1082             values[0] = (float)Math.atan2(R[1], R[5]);
   1083             values[1] = (float)Math.asin(-R[9]);
   1084             values[2] = (float)Math.atan2(-R[8], R[10]);
   1085         }
   1086         return values;
   1087     }
   1088 
   1089     /**
   1090      * Computes the Altitude in meters from the atmospheric pressure and the
   1091      * pressure at sea level.
   1092      * <p>
   1093      * Typically the atmospheric pressure is read from a
   1094      * {@link Sensor#TYPE_PRESSURE} sensor. The pressure at sea level must be
   1095      * known, usually it can be retrieved from airport databases in the
   1096      * vicinity. If unknown, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE}
   1097      * as an approximation, but absolute altitudes won't be accurate.
   1098      * </p>
   1099      * <p>
   1100      * To calculate altitude differences, you must calculate the difference
   1101      * between the altitudes at both points. If you don't know the altitude
   1102      * as sea level, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE} instead,
   1103      * which will give good results considering the range of pressure typically
   1104      * involved.
   1105      * </p>
   1106      * <p>
   1107      * <code><ul>
   1108      *  float altitude_difference =
   1109      *      getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point2)
   1110      *      - getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point1);
   1111      * </ul></code>
   1112      * </p>
   1113      *
   1114      * @param p0 pressure at sea level
   1115      * @param p atmospheric pressure
   1116      * @return Altitude in meters
   1117      */
   1118     public static float getAltitude(float p0, float p) {
   1119         final float coef = 1.0f / 5.255f;
   1120         return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef));
   1121     }
   1122 
   1123     /** Helper function to compute the angle change between two rotation matrices.
   1124      *  Given a current rotation matrix (R) and a previous rotation matrix
   1125      *  (prevR) computes the rotation around the z,x, and y axes which
   1126      *  transforms prevR to R.
   1127      *  outputs a 3 element vector containing the z,x, and y angle
   1128      *  change at indexes 0, 1, and 2 respectively.
   1129      * <p> Each input matrix is either as a 3x3 or 4x4 row-major matrix
   1130      * depending on the length of the passed array:
   1131      * <p>If the array length is 9, then the array elements represent this matrix
   1132      * <pre>
   1133      *   /  R[ 0]   R[ 1]   R[ 2]   \
   1134      *   |  R[ 3]   R[ 4]   R[ 5]   |
   1135      *   \  R[ 6]   R[ 7]   R[ 8]   /
   1136      *</pre>
   1137      * <p>If the array length is 16, then the array elements represent this matrix
   1138      * <pre>
   1139      *   /  R[ 0]   R[ 1]   R[ 2]   R[ 3]  \
   1140      *   |  R[ 4]   R[ 5]   R[ 6]   R[ 7]  |
   1141      *   |  R[ 8]   R[ 9]   R[10]   R[11]  |
   1142      *   \  R[12]   R[13]   R[14]   R[15]  /
   1143      *</pre>
   1144      * @param R current rotation matrix
   1145      * @param prevR previous rotation matrix
   1146      * @param angleChange an an array of floats (z, x, and y) in which the angle change is stored
   1147      */
   1148 
   1149     public static void getAngleChange( float[] angleChange, float[] R, float[] prevR) {
   1150         float rd1=0,rd4=0, rd6=0,rd7=0, rd8=0;
   1151         float ri0=0,ri1=0,ri2=0,ri3=0,ri4=0,ri5=0,ri6=0,ri7=0,ri8=0;
   1152         float pri0=0, pri1=0, pri2=0, pri3=0, pri4=0, pri5=0, pri6=0, pri7=0, pri8=0;
   1153 
   1154         if(R.length == 9) {
   1155             ri0 = R[0];
   1156             ri1 = R[1];
   1157             ri2 = R[2];
   1158             ri3 = R[3];
   1159             ri4 = R[4];
   1160             ri5 = R[5];
   1161             ri6 = R[6];
   1162             ri7 = R[7];
   1163             ri8 = R[8];
   1164         } else if(R.length == 16) {
   1165             ri0 = R[0];
   1166             ri1 = R[1];
   1167             ri2 = R[2];
   1168             ri3 = R[4];
   1169             ri4 = R[5];
   1170             ri5 = R[6];
   1171             ri6 = R[8];
   1172             ri7 = R[9];
   1173             ri8 = R[10];
   1174         }
   1175 
   1176         if(prevR.length == 9) {
   1177             pri0 = prevR[0];
   1178             pri1 = prevR[1];
   1179             pri2 = prevR[2];
   1180             pri3 = prevR[3];
   1181             pri4 = prevR[4];
   1182             pri5 = prevR[5];
   1183             pri6 = prevR[6];
   1184             pri7 = prevR[7];
   1185             pri8 = prevR[8];
   1186         } else if(prevR.length == 16) {
   1187             pri0 = prevR[0];
   1188             pri1 = prevR[1];
   1189             pri2 = prevR[2];
   1190             pri3 = prevR[4];
   1191             pri4 = prevR[5];
   1192             pri5 = prevR[6];
   1193             pri6 = prevR[8];
   1194             pri7 = prevR[9];
   1195             pri8 = prevR[10];
   1196         }
   1197 
   1198         // calculate the parts of the rotation difference matrix we need
   1199         // rd[i][j] = pri[0][i] * ri[0][j] + pri[1][i] * ri[1][j] + pri[2][i] * ri[2][j];
   1200 
   1201         rd1 = pri0 * ri1 + pri3 * ri4 + pri6 * ri7; //rd[0][1]
   1202         rd4 = pri1 * ri1 + pri4 * ri4 + pri7 * ri7; //rd[1][1]
   1203         rd6 = pri2 * ri0 + pri5 * ri3 + pri8 * ri6; //rd[2][0]
   1204         rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1]
   1205         rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2]
   1206 
   1207         angleChange[0] = (float)Math.atan2(rd1, rd4);
   1208         angleChange[1] = (float)Math.asin(-rd7);
   1209         angleChange[2] = (float)Math.atan2(-rd6, rd8);
   1210 
   1211     }
   1212 
   1213     /** Helper function to convert a rotation vector to a rotation matrix.
   1214      *  Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a
   1215      *  9  or 16 element rotation matrix in the array R.  R must have length 9 or 16.
   1216      *  If R.length == 9, the following matrix is returned:
   1217      * <pre>
   1218      *   /  R[ 0]   R[ 1]   R[ 2]   \
   1219      *   |  R[ 3]   R[ 4]   R[ 5]   |
   1220      *   \  R[ 6]   R[ 7]   R[ 8]   /
   1221      *</pre>
   1222      * If R.length == 16, the following matrix is returned:
   1223      * <pre>
   1224      *   /  R[ 0]   R[ 1]   R[ 2]   0  \
   1225      *   |  R[ 4]   R[ 5]   R[ 6]   0  |
   1226      *   |  R[ 8]   R[ 9]   R[10]   0  |
   1227      *   \  0       0       0       1  /
   1228      *</pre>
   1229      *  @param rotationVector the rotation vector to convert
   1230      *  @param R an array of floats in which to store the rotation matrix
   1231      */
   1232     public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) {
   1233 
   1234         float q0;
   1235         float q1 = rotationVector[0];
   1236         float q2 = rotationVector[1];
   1237         float q3 = rotationVector[2];
   1238 
   1239         if (rotationVector.length == 4) {
   1240             q0 = rotationVector[3];
   1241         } else {
   1242             q0 = 1 - q1*q1 - q2*q2 - q3*q3;
   1243             q0 = (q0 > 0) ? (float)Math.sqrt(q0) : 0;
   1244         }
   1245 
   1246         float sq_q1 = 2 * q1 * q1;
   1247         float sq_q2 = 2 * q2 * q2;
   1248         float sq_q3 = 2 * q3 * q3;
   1249         float q1_q2 = 2 * q1 * q2;
   1250         float q3_q0 = 2 * q3 * q0;
   1251         float q1_q3 = 2 * q1 * q3;
   1252         float q2_q0 = 2 * q2 * q0;
   1253         float q2_q3 = 2 * q2 * q3;
   1254         float q1_q0 = 2 * q1 * q0;
   1255 
   1256         if(R.length == 9) {
   1257             R[0] = 1 - sq_q2 - sq_q3;
   1258             R[1] = q1_q2 - q3_q0;
   1259             R[2] = q1_q3 + q2_q0;
   1260 
   1261             R[3] = q1_q2 + q3_q0;
   1262             R[4] = 1 - sq_q1 - sq_q3;
   1263             R[5] = q2_q3 - q1_q0;
   1264 
   1265             R[6] = q1_q3 - q2_q0;
   1266             R[7] = q2_q3 + q1_q0;
   1267             R[8] = 1 - sq_q1 - sq_q2;
   1268         } else if (R.length == 16) {
   1269             R[0] = 1 - sq_q2 - sq_q3;
   1270             R[1] = q1_q2 - q3_q0;
   1271             R[2] = q1_q3 + q2_q0;
   1272             R[3] = 0.0f;
   1273 
   1274             R[4] = q1_q2 + q3_q0;
   1275             R[5] = 1 - sq_q1 - sq_q3;
   1276             R[6] = q2_q3 - q1_q0;
   1277             R[7] = 0.0f;
   1278 
   1279             R[8] = q1_q3 - q2_q0;
   1280             R[9] = q2_q3 + q1_q0;
   1281             R[10] = 1 - sq_q1 - sq_q2;
   1282             R[11] = 0.0f;
   1283 
   1284             R[12] = R[13] = R[14] = 0.0f;
   1285             R[15] = 1.0f;
   1286         }
   1287     }
   1288 
   1289     /** Helper function to convert a rotation vector to a normalized quaternion.
   1290      *  Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a normalized
   1291      *  quaternion in the array Q.  The quaternion is stored as [w, x, y, z]
   1292      *  @param rv the rotation vector to convert
   1293      *  @param Q an array of floats in which to store the computed quaternion
   1294      */
   1295     public static void getQuaternionFromVector(float[] Q, float[] rv) {
   1296         if (rv.length == 4) {
   1297             Q[0] = rv[3];
   1298         } else {
   1299             Q[0] = 1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2];
   1300             Q[0] = (Q[0] > 0) ? (float)Math.sqrt(Q[0]) : 0;
   1301         }
   1302         Q[1] = rv[0];
   1303         Q[2] = rv[1];
   1304         Q[3] = rv[2];
   1305     }
   1306 
   1307     private LegacySensorManager getLegacySensorManager() {
   1308         synchronized (mSensorListByType) {
   1309             if (mLegacySensorManager == null) {
   1310                 Log.i(TAG, "This application is using deprecated SensorManager API which will "
   1311                         + "be removed someday.  Please consider switching to the new API.");
   1312                 mLegacySensorManager = new LegacySensorManager(this);
   1313             }
   1314             return mLegacySensorManager;
   1315         }
   1316     }
   1317 
   1318     /**
   1319      * Sensor event pool implementation.
   1320      * @hide
   1321      */
   1322     protected static final class SensorEventPool {
   1323         private final int mPoolSize;
   1324         private final SensorEvent mPool[];
   1325         private int mNumItemsInPool;
   1326 
   1327         private SensorEvent createSensorEvent() {
   1328             // maximal size for all legacy events is 3
   1329             return new SensorEvent(3);
   1330         }
   1331 
   1332         SensorEventPool(int poolSize) {
   1333             mPoolSize = poolSize;
   1334             mNumItemsInPool = poolSize;
   1335             mPool = new SensorEvent[poolSize];
   1336         }
   1337 
   1338         SensorEvent getFromPool() {
   1339             SensorEvent t = null;
   1340             synchronized (this) {
   1341                 if (mNumItemsInPool > 0) {
   1342                     // remove the "top" item from the pool
   1343                     final int index = mPoolSize - mNumItemsInPool;
   1344                     t = mPool[index];
   1345                     mPool[index] = null;
   1346                     mNumItemsInPool--;
   1347                 }
   1348             }
   1349             if (t == null) {
   1350                 // the pool was empty or this item was removed from the pool for
   1351                 // the first time. In any case, we need to create a new item.
   1352                 t = createSensorEvent();
   1353             }
   1354             return t;
   1355         }
   1356 
   1357         void returnToPool(SensorEvent t) {
   1358             synchronized (this) {
   1359                 // is there space left in the pool?
   1360                 if (mNumItemsInPool < mPoolSize) {
   1361                     // if so, return the item to the pool
   1362                     mNumItemsInPool++;
   1363                     final int index = mPoolSize - mNumItemsInPool;
   1364                     mPool[index] = t;
   1365                 }
   1366             }
   1367         }
   1368     }
   1369 }
   1370