• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
SensorManager()357     public SensorManager() {
358     }
359 
360     /**
361      * Gets the full list of sensors that are available.
362      * @hide
363      */
getFullSensorList()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
getSensors()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      */
getSensorList(int type)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      */
getDefaultSensor(int type)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
registerListener(SensorListener listener, int sensors)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
registerListener(SensorListener listener, int sensors, int rate)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
unregisterListener(SensorListener listener)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
unregisterListener(SensorListener listener, int sensors)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      */
unregisterListener(SensorEventListener listener, Sensor sensor)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      */
unregisterListener(SensorEventListener listener)546     public void unregisterListener(SensorEventListener listener) {
547         if (listener == null) {
548             return;
549         }
550 
551         unregisterListenerImpl(listener, null);
552     }
553 
554     /** @hide */
unregisterListenerImpl(SensorEventListener listener, Sensor sensor)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      */
registerListener(SensorEventListener listener, Sensor sensor, int rate)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      */
registerListener(SensorEventListener listener, Sensor sensor, int rate, Handler handler)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 */
registerListenerImpl(SensorEventListener listener, Sensor sensor, int delay, Handler handler)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 
getRotationMatrix(float[] R, float[] I, float[] gravity, float[] geomagnetic)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      */
getInclination(float[] I)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 
remapCoordinateSystem(float[] inR, int X, int Y, float[] outR)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 
remapCoordinateSystemImpl(float[] inR, int X, int Y, float[] outR)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      */
getOrientation(float[] R, float values[])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      */
getAltitude(float p0, float p)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 
getAngleChange( float[] angleChange, float[] R, float[] prevR)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      */
getRotationMatrixFromVector(float[] R, float[] rotationVector)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      */
getQuaternionFromVector(float[] Q, float[] rv)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 
getLegacySensorManager()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 
createSensorEvent()1327         private SensorEvent createSensorEvent() {
1328             // maximal size for all legacy events is 3
1329             return new SensorEvent(3);
1330         }
1331 
SensorEventPool(int poolSize)1332         SensorEventPool(int poolSize) {
1333             mPoolSize = poolSize;
1334             mNumItemsInPool = poolSize;
1335             mPool = new SensorEvent[poolSize];
1336         }
1337 
getFromPool()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 
returnToPool(SensorEvent t)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