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.annotation.SystemApi;
20 import android.os.Build;
21 import android.os.Handler;
22 import android.util.Log;
23 import android.util.SparseArray;
24 
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 
29 /**
30  * <p>
31  * SensorManager lets you access the device's {@link android.hardware.Sensor
32  * sensors}. Get an instance of this class by calling
33  * {@link android.content.Context#getSystemService(java.lang.String)
34  * Context.getSystemService()} with the argument
35  * {@link android.content.Context#SENSOR_SERVICE}.
36  * </p>
37  * <p>
38  * Always make sure to disable sensors you don't need, especially when your
39  * activity is paused. Failing to do so can drain the battery in just a few
40  * hours. Note that the system will <i>not</i> disable sensors automatically when
41  * the screen turns off.
42  * </p>
43  * <p class="note">
44  * Note: Don't use this mechanism with a Trigger Sensor, have a look
45  * at {@link TriggerEventListener}. {@link Sensor#TYPE_SIGNIFICANT_MOTION}
46  * is an example of a trigger sensor.
47  * </p>
48  * <pre class="prettyprint">
49  * public class SensorActivity extends Activity, implements SensorEventListener {
50  *     private final SensorManager mSensorManager;
51  *     private final Sensor mAccelerometer;
52  *
53  *     public SensorActivity() {
54  *         mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
55  *         mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
56  *     }
57  *
58  *     protected void onResume() {
59  *         super.onResume();
60  *         mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
61  *     }
62  *
63  *     protected void onPause() {
64  *         super.onPause();
65  *         mSensorManager.unregisterListener(this);
66  *     }
67  *
68  *     public void onAccuracyChanged(Sensor sensor, int accuracy) {
69  *     }
70  *
71  *     public void onSensorChanged(SensorEvent event) {
72  *     }
73  * }
74  * </pre>
75  *
76  * @see SensorEventListener
77  * @see SensorEvent
78  * @see Sensor
79  *
80  */
81 public abstract class SensorManager {
82     /** @hide */
83     protected static final String TAG = "SensorManager";
84 
85     private static final float[] mTempMatrix = new float[16];
86 
87     // Cached lists of sensors by type.  Guarded by mSensorListByType.
88     private final SparseArray<List<Sensor>> mSensorListByType =
89             new SparseArray<List<Sensor>>();
90 
91     // Legacy sensor manager implementation.  Guarded by mSensorListByType during initialization.
92     private LegacySensorManager mLegacySensorManager;
93 
94     /* NOTE: sensor IDs must be a power of 2 */
95 
96     /**
97      * A constant describing an orientation sensor. See
98      * {@link android.hardware.SensorListener SensorListener} for more details.
99      *
100      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
101      */
102     @Deprecated
103     public static final int SENSOR_ORIENTATION = 1 << 0;
104 
105     /**
106      * A constant describing an accelerometer. See
107      * {@link android.hardware.SensorListener SensorListener} for more details.
108      *
109      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
110      */
111     @Deprecated
112     public static final int SENSOR_ACCELEROMETER = 1 << 1;
113 
114     /**
115      * A constant describing a temperature sensor See
116      * {@link android.hardware.SensorListener SensorListener} for more details.
117      *
118      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
119      */
120     @Deprecated
121     public static final int SENSOR_TEMPERATURE = 1 << 2;
122 
123     /**
124      * A constant describing a magnetic sensor See
125      * {@link android.hardware.SensorListener SensorListener} for more details.
126      *
127      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
128      */
129     @Deprecated
130     public static final int SENSOR_MAGNETIC_FIELD = 1 << 3;
131 
132     /**
133      * A constant describing an ambient light sensor See
134      * {@link android.hardware.SensorListener SensorListener} for more details.
135      *
136      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
137      */
138     @Deprecated
139     public static final int SENSOR_LIGHT = 1 << 4;
140 
141     /**
142      * A constant describing a proximity sensor See
143      * {@link android.hardware.SensorListener SensorListener} for more details.
144      *
145      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
146      */
147     @Deprecated
148     public static final int SENSOR_PROXIMITY = 1 << 5;
149 
150     /**
151      * A constant describing a Tricorder See
152      * {@link android.hardware.SensorListener SensorListener} for more details.
153      *
154      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
155      */
156     @Deprecated
157     public static final int SENSOR_TRICORDER = 1 << 6;
158 
159     /**
160      * A constant describing an orientation sensor. See
161      * {@link android.hardware.SensorListener SensorListener} for more details.
162      *
163      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
164      */
165     @Deprecated
166     public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
167 
168     /**
169      * A constant that includes all sensors
170      *
171      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
172      */
173     @Deprecated
174     public static final int SENSOR_ALL = 0x7F;
175 
176     /**
177      * Smallest sensor ID
178      *
179      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
180      */
181     @Deprecated
182     public static final int SENSOR_MIN = SENSOR_ORIENTATION;
183 
184     /**
185      * Largest sensor ID
186      *
187      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
188      */
189     @Deprecated
190     public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1);
191 
192 
193     /**
194      * Index of the X value in the array returned by
195      * {@link android.hardware.SensorListener#onSensorChanged}
196      *
197      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
198      */
199     @Deprecated
200     public static final int DATA_X = 0;
201 
202     /**
203      * Index of the Y value in the array returned by
204      * {@link android.hardware.SensorListener#onSensorChanged}
205      *
206      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
207      */
208     @Deprecated
209     public static final int DATA_Y = 1;
210 
211     /**
212      * Index of the Z value in the array returned by
213      * {@link android.hardware.SensorListener#onSensorChanged}
214      *
215      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
216      */
217     @Deprecated
218     public static final int DATA_Z = 2;
219 
220     /**
221      * Offset to the untransformed values in the array returned by
222      * {@link android.hardware.SensorListener#onSensorChanged}
223      *
224      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
225      */
226     @Deprecated
227     public static final int RAW_DATA_INDEX = 3;
228 
229     /**
230      * Index of the untransformed X value in the array returned by
231      * {@link android.hardware.SensorListener#onSensorChanged}
232      *
233      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
234      */
235     @Deprecated
236     public static final int RAW_DATA_X = 3;
237 
238     /**
239      * Index of the untransformed Y value in the array returned by
240      * {@link android.hardware.SensorListener#onSensorChanged}
241      *
242      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
243      */
244     @Deprecated
245     public static final int RAW_DATA_Y = 4;
246 
247     /**
248      * Index of the untransformed Z value in the array returned by
249      * {@link android.hardware.SensorListener#onSensorChanged}
250      *
251      * @deprecated use {@link android.hardware.Sensor Sensor} instead.
252      */
253     @Deprecated
254     public static final int RAW_DATA_Z = 5;
255 
256     /** Standard gravity (g) on Earth. This value is equivalent to 1G */
257     public static final float STANDARD_GRAVITY = 9.80665f;
258 
259     /** Sun's gravity in SI units (m/s^2) */
260     public static final float GRAVITY_SUN             = 275.0f;
261     /** Mercury's gravity in SI units (m/s^2) */
262     public static final float GRAVITY_MERCURY         = 3.70f;
263     /** Venus' gravity in SI units (m/s^2) */
264     public static final float GRAVITY_VENUS           = 8.87f;
265     /** Earth's gravity in SI units (m/s^2) */
266     public static final float GRAVITY_EARTH           = 9.80665f;
267     /** The Moon's gravity in SI units (m/s^2) */
268     public static final float GRAVITY_MOON            = 1.6f;
269     /** Mars' gravity in SI units (m/s^2) */
270     public static final float GRAVITY_MARS            = 3.71f;
271     /** Jupiter's gravity in SI units (m/s^2) */
272     public static final float GRAVITY_JUPITER         = 23.12f;
273     /** Saturn's gravity in SI units (m/s^2) */
274     public static final float GRAVITY_SATURN          = 8.96f;
275     /** Uranus' gravity in SI units (m/s^2) */
276     public static final float GRAVITY_URANUS          = 8.69f;
277     /** Neptune's gravity in SI units (m/s^2) */
278     public static final float GRAVITY_NEPTUNE         = 11.0f;
279     /** Pluto's gravity in SI units (m/s^2) */
280     public static final float GRAVITY_PLUTO           = 0.6f;
281     /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */
282     public static final float GRAVITY_DEATH_STAR_I    = 0.000000353036145f;
283     /** Gravity on the island */
284     public static final float GRAVITY_THE_ISLAND      = 4.815162342f;
285 
286 
287     /** Maximum magnetic field on Earth's surface */
288     public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f;
289     /** Minimum magnetic field on Earth's surface */
290     public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;
291 
292 
293     /** Standard atmosphere, or average sea-level pressure in hPa (millibar) */
294     public static final float PRESSURE_STANDARD_ATMOSPHERE = 1013.25f;
295 
296 
297     /** Maximum luminance of sunlight in lux */
298     public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
299     /** luminance of sunlight in lux */
300     public static final float LIGHT_SUNLIGHT     = 110000.0f;
301     /** luminance in shade in lux */
302     public static final float LIGHT_SHADE        = 20000.0f;
303     /** luminance under an overcast sky in lux */
304     public static final float LIGHT_OVERCAST     = 10000.0f;
305     /** luminance at sunrise in lux */
306     public static final float LIGHT_SUNRISE      = 400.0f;
307     /** luminance under a cloudy sky in lux */
308     public static final float LIGHT_CLOUDY       = 100.0f;
309     /** luminance at night with full moon in lux */
310     public static final float LIGHT_FULLMOON     = 0.25f;
311     /** luminance at night with no moon in lux*/
312     public static final float LIGHT_NO_MOON      = 0.001f;
313 
314 
315     /** get sensor data as fast as possible */
316     public static final int SENSOR_DELAY_FASTEST = 0;
317     /** rate suitable for games */
318     public static final int SENSOR_DELAY_GAME = 1;
319     /** rate suitable for the user interface  */
320     public static final int SENSOR_DELAY_UI = 2;
321     /** rate (default) suitable for screen orientation changes */
322     public static final int SENSOR_DELAY_NORMAL = 3;
323 
324 
325     /**
326       * The values returned by this sensor cannot be trusted because the sensor
327       * had no contact with what it was measuring (for example, the heart rate
328       * monitor is not in contact with the user).
329       */
330     public static final int SENSOR_STATUS_NO_CONTACT = -1;
331 
332     /**
333      * The values returned by this sensor cannot be trusted, calibration is
334      * needed or the environment doesn't allow readings
335      */
336     public static final int SENSOR_STATUS_UNRELIABLE = 0;
337 
338     /**
339      * This sensor is reporting data with low accuracy, calibration with the
340      * environment is needed
341      */
342     public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
343 
344     /**
345      * This sensor is reporting data with an average level of accuracy,
346      * calibration with the environment may improve the readings
347      */
348     public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;
349 
350     /** This sensor is reporting data with maximum accuracy */
351     public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;
352 
353     /** see {@link #remapCoordinateSystem} */
354     public static final int AXIS_X = 1;
355     /** see {@link #remapCoordinateSystem} */
356     public static final int AXIS_Y = 2;
357     /** see {@link #remapCoordinateSystem} */
358     public static final int AXIS_Z = 3;
359     /** see {@link #remapCoordinateSystem} */
360     public static final int AXIS_MINUS_X = AXIS_X | 0x80;
361     /** see {@link #remapCoordinateSystem} */
362     public static final int AXIS_MINUS_Y = AXIS_Y | 0x80;
363     /** see {@link #remapCoordinateSystem} */
364     public static final int AXIS_MINUS_Z = AXIS_Z | 0x80;
365 
366 
367     /**
368      * {@hide}
369      */
SensorManager()370     public SensorManager() {
371     }
372 
373     /**
374      * Gets the full list of sensors that are available.
375      * @hide
376      */
getFullSensorList()377     protected abstract List<Sensor> getFullSensorList();
378 
379     /**
380      * @return available sensors.
381      * @deprecated This method is deprecated, use
382      *             {@link SensorManager#getSensorList(int)} instead
383      */
384     @Deprecated
getSensors()385     public int getSensors() {
386         return getLegacySensorManager().getSensors();
387     }
388 
389     /**
390      * Use this method to get the list of available sensors of a certain type.
391      * Make multiple calls to get sensors of different types or use
392      * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the
393      * sensors.
394      *
395      * <p class="note">
396      * NOTE: Both wake-up and non wake-up sensors matching the given type are
397      * returned. Check {@link Sensor#isWakeUpSensor()} to know the wake-up properties
398      * of the returned {@link Sensor}.
399      * </p>
400      *
401      * @param type
402      *        of sensors requested
403      *
404      * @return a list of sensors matching the asked type.
405      *
406      * @see #getDefaultSensor(int)
407      * @see Sensor
408      */
getSensorList(int type)409     public List<Sensor> getSensorList(int type) {
410         // cache the returned lists the first time
411         List<Sensor> list;
412         final List<Sensor> fullList = getFullSensorList();
413         synchronized (mSensorListByType) {
414             list = mSensorListByType.get(type);
415             if (list == null) {
416                 if (type == Sensor.TYPE_ALL) {
417                     list = fullList;
418                 } else {
419                     list = new ArrayList<Sensor>();
420                     for (Sensor i : fullList) {
421                         if (i.getType() == type)
422                             list.add(i);
423                     }
424                 }
425                 list = Collections.unmodifiableList(list);
426                 mSensorListByType.append(type, list);
427             }
428         }
429         return list;
430     }
431 
432     /**
433      * Use this method to get the default sensor for a given type. Note that the
434      * returned sensor could be a composite sensor, and its data could be
435      * averaged or filtered. If you need to access the raw sensors use
436      * {@link SensorManager#getSensorList(int) getSensorList}.
437      *
438      * @param type
439      *         of sensors requested
440      *
441      * @return the default sensor matching the requested type if one exists and the application
442      *         has the necessary permissions, or null otherwise.
443      *
444      * @see #getSensorList(int)
445      * @see Sensor
446      */
getDefaultSensor(int type)447     public Sensor getDefaultSensor(int type) {
448         // TODO: need to be smarter, for now, just return the 1st sensor
449         List<Sensor> l = getSensorList(type);
450         boolean wakeUpSensor = false;
451         // For the following sensor types, return a wake-up sensor. These types are by default
452         // defined as wake-up sensors. For the rest of the SDK defined sensor types return a
453         // non_wake-up version.
454         if (type == Sensor.TYPE_PROXIMITY || type == Sensor.TYPE_SIGNIFICANT_MOTION ||
455                 type == Sensor.TYPE_TILT_DETECTOR || type == Sensor.TYPE_WAKE_GESTURE ||
456                 type == Sensor.TYPE_GLANCE_GESTURE || type == Sensor.TYPE_PICK_UP_GESTURE ||
457                 type == Sensor.TYPE_WRIST_TILT_GESTURE) {
458             wakeUpSensor = true;
459         }
460 
461         for (Sensor sensor : l) {
462             if (sensor.isWakeUpSensor() == wakeUpSensor) return sensor;
463         }
464         return null;
465     }
466 
467     /**
468      * Return a Sensor with the given type and wakeUp properties. If multiple sensors of this
469      * type exist, any one of them may be returned.
470      * <p>
471      * For example,
472      * <ul>
473      *     <li>getDefaultSensor({@link Sensor#TYPE_ACCELEROMETER}, true) returns a wake-up accelerometer
474      *     sensor if it exists. </li>
475      *     <li>getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, false) returns a non wake-up proximity
476      *     sensor if it exists. </li>
477      *     <li>getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, true) returns a wake-up proximity sensor
478      *     which is the same as the Sensor returned by {@link #getDefaultSensor(int)}. </li>
479      * </ul>
480      * </p>
481      * <p class="note">
482      * Note: Sensors like {@link Sensor#TYPE_PROXIMITY} and {@link Sensor#TYPE_SIGNIFICANT_MOTION}
483      * are declared as wake-up sensors by default.
484      * </p>
485      * @param type
486      *        type of sensor requested
487      * @param wakeUp
488      *        flag to indicate whether the Sensor is a wake-up or non wake-up sensor.
489      * @return the default sensor matching the requested type and wakeUp properties if one exists
490      *         and the application has the necessary permissions, or null otherwise.
491      * @see Sensor#isWakeUpSensor()
492      */
getDefaultSensor(int type, boolean wakeUp)493     public Sensor getDefaultSensor(int type, boolean wakeUp) {
494         List<Sensor> l = getSensorList(type);
495         for (Sensor sensor : l) {
496             if (sensor.isWakeUpSensor() == wakeUp)
497                 return sensor;
498         }
499         return null;
500     }
501 
502     /**
503      * Registers a listener for given sensors.
504      *
505      * @deprecated This method is deprecated, use
506      *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
507      *             instead.
508      *
509      * @param listener
510      *        sensor listener object
511      *
512      * @param sensors
513      *        a bit masks of the sensors to register to
514      *
515      * @return <code>true</code> if the sensor is supported and successfully
516      *         enabled
517      */
518     @Deprecated
registerListener(SensorListener listener, int sensors)519     public boolean registerListener(SensorListener listener, int sensors) {
520         return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
521     }
522 
523     /**
524      * Registers a SensorListener for given sensors.
525      *
526      * @deprecated This method is deprecated, use
527      *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
528      *             instead.
529      *
530      * @param listener
531      *        sensor listener object
532      *
533      * @param sensors
534      *        a bit masks of the sensors to register to
535      *
536      * @param rate
537      *        rate of events. This is only a hint to the system. events may be
538      *        received faster or slower than the specified rate. Usually events
539      *        are received faster. The value must be one of
540      *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
541      *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
542      *
543      * @return <code>true</code> if the sensor is supported and successfully
544      *         enabled
545      */
546     @Deprecated
registerListener(SensorListener listener, int sensors, int rate)547     public boolean registerListener(SensorListener listener, int sensors, int rate) {
548         return getLegacySensorManager().registerListener(listener, sensors, rate);
549     }
550 
551     /**
552      * Unregisters a listener for all sensors.
553      *
554      * @deprecated This method is deprecated, use
555      *             {@link SensorManager#unregisterListener(SensorEventListener)}
556      *             instead.
557      *
558      * @param listener
559      *        a SensorListener object
560      */
561     @Deprecated
unregisterListener(SensorListener listener)562     public void unregisterListener(SensorListener listener) {
563         unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
564     }
565 
566     /**
567      * Unregisters a listener for the sensors with which it is registered.
568      *
569      * @deprecated This method is deprecated, use
570      *             {@link SensorManager#unregisterListener(SensorEventListener, Sensor)}
571      *             instead.
572      *
573      * @param listener
574      *        a SensorListener object
575      *
576      * @param sensors
577      *        a bit masks of the sensors to unregister from
578      */
579     @Deprecated
unregisterListener(SensorListener listener, int sensors)580     public void unregisterListener(SensorListener listener, int sensors) {
581         getLegacySensorManager().unregisterListener(listener, sensors);
582     }
583 
584     /**
585      * Unregisters a listener for the sensors with which it is registered.
586      *
587      * <p class="note"></p>
588      * Note: Don't use this method with a one shot trigger sensor such as
589      * {@link Sensor#TYPE_SIGNIFICANT_MOTION}.
590      * Use {@link #cancelTriggerSensor(TriggerEventListener, Sensor)} instead.
591      * </p>
592      *
593      * @param listener
594      *        a SensorEventListener object
595      *
596      * @param sensor
597      *        the sensor to unregister from
598      *
599      * @see #unregisterListener(SensorEventListener)
600      * @see #registerListener(SensorEventListener, Sensor, int)
601      */
unregisterListener(SensorEventListener listener, Sensor sensor)602     public void unregisterListener(SensorEventListener listener, Sensor sensor) {
603         if (listener == null || sensor == null) {
604             return;
605         }
606 
607         unregisterListenerImpl(listener, sensor);
608     }
609 
610     /**
611      * Unregisters a listener for all sensors.
612      *
613      * @param listener
614      *        a SensorListener object
615      *
616      * @see #unregisterListener(SensorEventListener, Sensor)
617      * @see #registerListener(SensorEventListener, Sensor, int)
618      *
619      */
unregisterListener(SensorEventListener listener)620     public void unregisterListener(SensorEventListener listener) {
621         if (listener == null) {
622             return;
623         }
624 
625         unregisterListenerImpl(listener, null);
626     }
627 
628     /** @hide */
unregisterListenerImpl(SensorEventListener listener, Sensor sensor)629     protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor sensor);
630 
631     /**
632      * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
633      * sensor at the given sampling frequency.
634      * <p>
635      * The events will be delivered to the provided {@code SensorEventListener} as soon as they are
636      * available. To reduce the power consumption, applications can use
637      * {@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a
638      * positive non-zero maximum reporting latency.
639      * </p>
640      * <p>
641      * In the case of non-wake-up sensors, the events are only delivered while the Application
642      * Processor (AP) is not in suspend mode. See {@link Sensor#isWakeUpSensor()} for more details.
643      * To ensure delivery of events from non-wake-up sensors even when the screen is OFF, the
644      * application registering to the sensor must hold a partial wake-lock to keep the AP awake,
645      * otherwise some events might be lost while the AP is asleep. Note that although events might
646      * be lost while the AP is asleep, the sensor will still consume power if it is not explicitly
647      * deactivated by the application. Applications must unregister their {@code
648      * SensorEventListener}s in their activity's {@code onPause()} method to avoid consuming power
649      * while the device is inactive.  See {@link #registerListener(SensorEventListener, Sensor, int,
650      * int)} for more details on hardware FIFO (queueing) capabilities and when some sensor events
651      * might be lost.
652      * </p>
653      * <p>
654      * In the case of wake-up sensors, each event generated by the sensor will cause the AP to
655      * wake-up, ensuring that each event can be delivered. Because of this, registering to a wake-up
656      * sensor has very significant power implications. Call {@link Sensor#isWakeUpSensor()} to check
657      * whether a sensor is a wake-up sensor. See
658      * {@link #registerListener(SensorEventListener, Sensor, int, int)} for information on how to
659      * reduce the power impact of registering to wake-up sensors.
660      * </p>
661      * <p class="note">
662      * Note: Don't use this method with one-shot trigger sensors such as
663      * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use
664      * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. Use
665      * {@link Sensor#getReportingMode()} to obtain the reporting mode of a given sensor.
666      * </p>
667      *
668      * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object.
669      * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
670      * @param samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are
671      *            delivered at. This is only a hint to the system. Events may be received faster or
672      *            slower than the specified rate. Usually events are received faster. The value must
673      *            be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
674      *            {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired delay
675      *            between events in microseconds. Specifying the delay in microseconds only works
676      *            from Android 2.3 (API level 9) onwards. For earlier releases, you must use one of
677      *            the {@code SENSOR_DELAY_*} constants.
678      * @return <code>true</code> if the sensor is supported and successfully enabled.
679      * @see #registerListener(SensorEventListener, Sensor, int, Handler)
680      * @see #unregisterListener(SensorEventListener)
681      * @see #unregisterListener(SensorEventListener, Sensor)
682      */
registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs)683     public boolean registerListener(SensorEventListener listener, Sensor sensor,
684             int samplingPeriodUs) {
685         return registerListener(listener, sensor, samplingPeriodUs, null);
686     }
687 
688     /**
689      * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
690      * sensor at the given sampling frequency and the given maximum reporting latency.
691      * <p>
692      * This function is similar to {@link #registerListener(SensorEventListener, Sensor, int)} but
693      * it allows events to stay temporarily in the hardware FIFO (queue) before being delivered. The
694      * events can be stored in the hardware FIFO up to {@code maxReportLatencyUs} microseconds. Once
695      * one of the events in the FIFO needs to be reported, all of the events in the FIFO are
696      * reported sequentially. This means that some events will be reported before the maximum
697      * reporting latency has elapsed.
698      * </p><p>
699      * When {@code maxReportLatencyUs} is 0, the call is equivalent to a call to
700      * {@link #registerListener(SensorEventListener, Sensor, int)}, as it requires the events to be
701      * delivered as soon as possible.
702      * </p><p>
703      * When {@code sensor.maxFifoEventCount()} is 0, the sensor does not use a FIFO, so the call
704      * will also be equivalent to {@link #registerListener(SensorEventListener, Sensor, int)}.
705      * </p><p>
706      * Setting {@code maxReportLatencyUs} to a positive value allows to reduce the number of
707      * interrupts the AP (Application Processor) receives, hence reducing power consumption, as the
708      * AP can switch to a lower power state while the sensor is capturing the data. This is
709      * especially important when registering to wake-up sensors, for which each interrupt causes the
710      * AP to wake up if it was in suspend mode. See {@link Sensor#isWakeUpSensor()} for more
711      * information on wake-up sensors.
712      * </p>
713      * <p class="note">
714      * </p>
715      * Note: Don't use this method with one-shot trigger sensors such as
716      * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use
717      * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p>
718      *
719      * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
720      *            that will receive the sensor events. If the application is interested in receiving
721      *            flush complete notifications, it should register with
722      *            {@link android.hardware.SensorEventListener SensorEventListener2} instead.
723      * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
724      * @param samplingPeriodUs The desired delay between two consecutive events in microseconds.
725      *            This is only a hint to the system. Events may be received faster or slower than
726      *            the specified rate. Usually events are received faster. Can be one of
727      *            {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
728      *            {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in
729      *            microseconds.
730      * @param maxReportLatencyUs Maximum time in microseconds that events can be delayed before
731      *            being reported to the application. A large value allows reducing the power
732      *            consumption associated with the sensor. If maxReportLatencyUs is set to zero,
733      *            events are delivered as soon as they are available, which is equivalent to calling
734      *            {@link #registerListener(SensorEventListener, Sensor, int)}.
735      * @return <code>true</code> if the sensor is supported and successfully enabled.
736      * @see #registerListener(SensorEventListener, Sensor, int)
737      * @see #unregisterListener(SensorEventListener)
738      * @see #flush(SensorEventListener)
739      */
registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, int maxReportLatencyUs)740     public boolean registerListener(SensorEventListener listener, Sensor sensor,
741             int samplingPeriodUs, int maxReportLatencyUs) {
742         int delay = getDelay(samplingPeriodUs);
743         return registerListenerImpl(listener, sensor, delay, null, maxReportLatencyUs, 0);
744     }
745 
746     /**
747      * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
748      * sensor. Events are delivered in continuous mode as soon as they are available. To reduce the
749      * power consumption, applications can use
750      * {@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a
751      * positive non-zero maximum reporting latency.
752      * <p class="note">
753      * </p>
754      * Note: Don't use this method with a one shot trigger sensor such as
755      * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use
756      * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p>
757      *
758      * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object.
759      * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
760      * @param samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are
761      *            delivered at. This is only a hint to the system. Events may be received faster or
762      *            slower than the specified rate. Usually events are received faster. The value must
763      *            be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
764      *            {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired
765      *            delay between events in microseconds. Specifying the delay in microseconds only
766      *            works from Android 2.3 (API level 9) onwards. For earlier releases, you must use
767      *            one of the {@code SENSOR_DELAY_*} constants.
768      * @param handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent
769      *            sensor events} will be delivered to.
770      * @return <code>true</code> if the sensor is supported and successfully enabled.
771      * @see #registerListener(SensorEventListener, Sensor, int)
772      * @see #unregisterListener(SensorEventListener)
773      * @see #unregisterListener(SensorEventListener, Sensor)
774      */
registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, Handler handler)775     public boolean registerListener(SensorEventListener listener, Sensor sensor,
776             int samplingPeriodUs, Handler handler) {
777         int delay = getDelay(samplingPeriodUs);
778         return registerListenerImpl(listener, sensor, delay, handler, 0, 0);
779     }
780 
781     /**
782      * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
783      * sensor at the given sampling frequency and the given maximum reporting latency.
784      *
785      * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
786      *            that will receive the sensor events. If the application is interested in receiving
787      *            flush complete notifications, it should register with
788      *            {@link android.hardware.SensorEventListener SensorEventListener2} instead.
789      * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
790      * @param samplingPeriodUs The desired delay between two consecutive events in microseconds.
791      *            This is only a hint to the system. Events may be received faster or slower than
792      *            the specified rate. Usually events are received faster. Can be one of
793      *            {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
794      *            {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in
795      *            microseconds.
796      * @param maxReportLatencyUs Maximum time in microseconds that events can be delayed before
797      *            being reported to the application. A large value allows reducing the power
798      *            consumption associated with the sensor. If maxReportLatencyUs is set to zero,
799      *            events are delivered as soon as they are available, which is equivalent to calling
800      *            {@link #registerListener(SensorEventListener, Sensor, int)}.
801      * @param handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent
802      *            sensor events} will be delivered to.
803      * @return <code>true</code> if the sensor is supported and successfully enabled.
804      * @see #registerListener(SensorEventListener, Sensor, int, int)
805      */
registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, int maxReportLatencyUs, Handler handler)806     public boolean registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs,
807             int maxReportLatencyUs, Handler handler) {
808         int delayUs = getDelay(samplingPeriodUs);
809         return registerListenerImpl(listener, sensor, delayUs, handler, maxReportLatencyUs, 0);
810     }
811 
812     /** @hide */
registerListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags)813     protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
814             int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags);
815 
816 
817     /**
818      * Flushes the FIFO of all the sensors registered for this listener. If there are events
819      * in the FIFO of the sensor, they are returned as if the maxReportLantecy of the FIFO has
820      * expired. Events are returned in the usual way through the SensorEventListener.
821      * This call doesn't affect the maxReportLantecy for this sensor. This call is asynchronous and
822      * returns immediately.
823      * {@link android.hardware.SensorEventListener2#onFlushCompleted onFlushCompleted} is called
824      * after all the events in the batch at the time of calling this method have been delivered
825      * successfully. If the hardware doesn't support flush, it still returns true and a trivial
826      * flush complete event is sent after the current event for all the clients registered for this
827      * sensor.
828      *
829      * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
830      *        which was previously used in a registerListener call.
831      * @return <code>true</code> if the flush is initiated successfully on all the sensors
832      *         registered for this listener, false if no sensor is previously registered for this
833      *         listener or flush on one of the sensors fails.
834      * @see #registerListener(SensorEventListener, Sensor, int, int)
835      * @throws IllegalArgumentException when listener is null.
836      */
flush(SensorEventListener listener)837     public boolean flush(SensorEventListener listener) {
838         return flushImpl(listener);
839     }
840 
841     /** @hide */
flushImpl(SensorEventListener listener)842     protected abstract boolean flushImpl(SensorEventListener listener);
843 
844     /**
845      * <p>
846      * Computes the inclination matrix <b>I</b> as well as the rotation matrix
847      * <b>R</b> transforming a vector from the device coordinate system to the
848      * world's coordinate system which is defined as a direct orthonormal basis,
849      * where:
850      * </p>
851      *
852      * <ul>
853      * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
854      * the ground at the device's current location and roughly points East).</li>
855      * <li>Y is tangential to the ground at the device's current location and
856      * points towards the magnetic North Pole.</li>
857      * <li>Z points towards the sky and is perpendicular to the ground.</li>
858      * </ul>
859      *
860      * <p>
861      * <center><img src="../../../images/axis_globe.png"
862      * alt="World coordinate-system diagram." border="0" /></center>
863      * </p>
864      *
865      * <p>
866      * <hr>
867      * <p>
868      * By definition:
869      * <p>
870      * [0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity)
871      * <p>
872      * [0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b> (m = magnitude of
873      * geomagnetic field)
874      * <p>
875      * <b>R</b> is the identity matrix when the device is aligned with the
876      * world's coordinate system, that is, when the device's X axis points
877      * toward East, the Y axis points to the North Pole and the device is facing
878      * the sky.
879      *
880      * <p>
881      * <b>I</b> is a rotation matrix transforming the geomagnetic vector into
882      * the same coordinate space as gravity (the world's coordinate space).
883      * <b>I</b> is a simple rotation around the X axis. The inclination angle in
884      * radians can be computed with {@link #getInclination}.
885      * <hr>
886      *
887      * <p>
888      * Each matrix is returned either as a 3x3 or 4x4 row-major matrix depending
889      * on the length of the passed array:
890      * <p>
891      * <u>If the array length is 16:</u>
892      *
893      * <pre>
894      *   /  M[ 0]   M[ 1]   M[ 2]   M[ 3]  \
895      *   |  M[ 4]   M[ 5]   M[ 6]   M[ 7]  |
896      *   |  M[ 8]   M[ 9]   M[10]   M[11]  |
897      *   \  M[12]   M[13]   M[14]   M[15]  /
898      *</pre>
899      *
900      * This matrix is ready to be used by OpenGL ES's
901      * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int)
902      * glLoadMatrixf(float[], int)}.
903      * <p>
904      * Note that because OpenGL matrices are column-major matrices you must
905      * transpose the matrix before using it. However, since the matrix is a
906      * rotation matrix, its transpose is also its inverse, conveniently, it is
907      * often the inverse of the rotation that is needed for rendering; it can
908      * therefore be used with OpenGL ES directly.
909      * <p>
910      * Also note that the returned matrices always have this form:
911      *
912      * <pre>
913      *   /  M[ 0]   M[ 1]   M[ 2]   0  \
914      *   |  M[ 4]   M[ 5]   M[ 6]   0  |
915      *   |  M[ 8]   M[ 9]   M[10]   0  |
916      *   \      0       0       0   1  /
917      *</pre>
918      *
919      * <p>
920      * <u>If the array length is 9:</u>
921      *
922      * <pre>
923      *   /  M[ 0]   M[ 1]   M[ 2]  \
924      *   |  M[ 3]   M[ 4]   M[ 5]  |
925      *   \  M[ 6]   M[ 7]   M[ 8]  /
926      *</pre>
927      *
928      * <hr>
929      * <p>
930      * The inverse of each matrix can be computed easily by taking its
931      * transpose.
932      *
933      * <p>
934      * The matrices returned by this function are meaningful only when the
935      * device is not free-falling and it is not close to the magnetic north. If
936      * the device is accelerating, or placed into a strong magnetic field, the
937      * returned matrices may be inaccurate.
938      *
939      * @param R
940      *        is an array of 9 floats holding the rotation matrix <b>R</b> when
941      *        this function returns. R can be null.
942      *        <p>
943      *
944      * @param I
945      *        is an array of 9 floats holding the rotation matrix <b>I</b> when
946      *        this function returns. I can be null.
947      *        <p>
948      *
949      * @param gravity
950      *        is an array of 3 floats containing the gravity vector expressed in
951      *        the device's coordinate. You can simply use the
952      *        {@link android.hardware.SensorEvent#values values} returned by a
953      *        {@link android.hardware.SensorEvent SensorEvent} of a
954      *        {@link android.hardware.Sensor Sensor} of type
955      *        {@link android.hardware.Sensor#TYPE_ACCELEROMETER
956      *        TYPE_ACCELEROMETER}.
957      *        <p>
958      *
959      * @param geomagnetic
960      *        is an array of 3 floats containing the geomagnetic vector
961      *        expressed in the device's coordinate. You can simply use the
962      *        {@link android.hardware.SensorEvent#values values} returned by a
963      *        {@link android.hardware.SensorEvent SensorEvent} of a
964      *        {@link android.hardware.Sensor Sensor} of type
965      *        {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD
966      *        TYPE_MAGNETIC_FIELD}.
967      *
968      * @return <code>true</code> on success, <code>false</code> on failure (for
969      *         instance, if the device is in free fall). Free fall is defined as
970      *         condition when the magnitude of the gravity is less than 1/10 of
971      *         the nominal value. On failure the output matrices are not modified.
972      *
973      * @see #getInclination(float[])
974      * @see #getOrientation(float[], float[])
975      * @see #remapCoordinateSystem(float[], int, int, float[])
976      */
977 
getRotationMatrix(float[] R, float[] I, float[] gravity, float[] geomagnetic)978     public static boolean getRotationMatrix(float[] R, float[] I,
979             float[] gravity, float[] geomagnetic) {
980         // TODO: move this to native code for efficiency
981         float Ax = gravity[0];
982         float Ay = gravity[1];
983         float Az = gravity[2];
984 
985         final float normsqA = (Ax*Ax + Ay*Ay + Az*Az);
986         final float g = 9.81f;
987         final float freeFallGravitySquared = 0.01f * g * g;
988         if (normsqA < freeFallGravitySquared) {
989             // gravity less than 10% of normal value
990             return false;
991         }
992 
993         final float Ex = geomagnetic[0];
994         final float Ey = geomagnetic[1];
995         final float Ez = geomagnetic[2];
996         float Hx = Ey*Az - Ez*Ay;
997         float Hy = Ez*Ax - Ex*Az;
998         float Hz = Ex*Ay - Ey*Ax;
999         final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
1000 
1001         if (normH < 0.1f) {
1002             // device is close to free fall (or in space?), or close to
1003             // magnetic north pole. Typical values are  > 100.
1004             return false;
1005         }
1006         final float invH = 1.0f / normH;
1007         Hx *= invH;
1008         Hy *= invH;
1009         Hz *= invH;
1010         final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
1011         Ax *= invA;
1012         Ay *= invA;
1013         Az *= invA;
1014         final float Mx = Ay*Hz - Az*Hy;
1015         final float My = Az*Hx - Ax*Hz;
1016         final float Mz = Ax*Hy - Ay*Hx;
1017         if (R != null) {
1018             if (R.length == 9) {
1019                 R[0] = Hx;     R[1] = Hy;     R[2] = Hz;
1020                 R[3] = Mx;     R[4] = My;     R[5] = Mz;
1021                 R[6] = Ax;     R[7] = Ay;     R[8] = Az;
1022             } else if (R.length == 16) {
1023                 R[0]  = Hx;    R[1]  = Hy;    R[2]  = Hz;   R[3]  = 0;
1024                 R[4]  = Mx;    R[5]  = My;    R[6]  = Mz;   R[7]  = 0;
1025                 R[8]  = Ax;    R[9]  = Ay;    R[10] = Az;   R[11] = 0;
1026                 R[12] = 0;     R[13] = 0;     R[14] = 0;    R[15] = 1;
1027             }
1028         }
1029         if (I != null) {
1030             // compute the inclination matrix by projecting the geomagnetic
1031             // vector onto the Z (gravity) and X (horizontal component
1032             // of geomagnetic vector) axes.
1033             final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
1034             final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
1035             final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
1036             if (I.length == 9) {
1037                 I[0] = 1;     I[1] = 0;     I[2] = 0;
1038                 I[3] = 0;     I[4] = c;     I[5] = s;
1039                 I[6] = 0;     I[7] =-s;     I[8] = c;
1040             } else if (I.length == 16) {
1041                 I[0] = 1;     I[1] = 0;     I[2] = 0;
1042                 I[4] = 0;     I[5] = c;     I[6] = s;
1043                 I[8] = 0;     I[9] =-s;     I[10]= c;
1044                 I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
1045                 I[15] = 1;
1046             }
1047         }
1048         return true;
1049     }
1050 
1051     /**
1052      * Computes the geomagnetic inclination angle in radians from the
1053      * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}.
1054      *
1055      * @param I
1056      *        inclination matrix see {@link #getRotationMatrix}.
1057      *
1058      * @return The geomagnetic inclination angle in radians.
1059      *
1060      * @see #getRotationMatrix(float[], float[], float[], float[])
1061      * @see #getOrientation(float[], float[])
1062      * @see GeomagneticField
1063      *
1064      */
getInclination(float[] I)1065     public static float getInclination(float[] I) {
1066         if (I.length == 9) {
1067             return (float)Math.atan2(I[5], I[4]);
1068         } else {
1069             return (float)Math.atan2(I[6], I[5]);
1070         }
1071     }
1072 
1073     /**
1074      * <p>
1075      * Rotates the supplied rotation matrix so it is expressed in a different
1076      * coordinate system. This is typically used when an application needs to
1077      * compute the three orientation angles of the device (see
1078      * {@link #getOrientation}) in a different coordinate system.
1079      * </p>
1080      *
1081      * <p>
1082      * When the rotation matrix is used for drawing (for instance with OpenGL
1083      * ES), it usually <b>doesn't need</b> to be transformed by this function,
1084      * unless the screen is physically rotated, in which case you can use
1085      * {@link android.view.Display#getRotation() Display.getRotation()} to
1086      * retrieve the current rotation of the screen. Note that because the user
1087      * is generally free to rotate their screen, you often should consider the
1088      * rotation in deciding the parameters to use here.
1089      * </p>
1090      *
1091      * <p>
1092      * <u>Examples:</u>
1093      * <p>
1094      *
1095      * <ul>
1096      * <li>Using the camera (Y axis along the camera's axis) for an augmented
1097      * reality application where the rotation angles are needed:</li>
1098      *
1099      * <p>
1100      * <ul>
1101      * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code>
1102      * </ul>
1103      * </p>
1104      *
1105      * <li>Using the device as a mechanical compass when rotation is
1106      * {@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:</li>
1107      *
1108      * <p>
1109      * <ul>
1110      * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code>
1111      * </ul>
1112      * </p>
1113      *
1114      * Beware of the above example. This call is needed only to account for a
1115      * rotation from its natural orientation when calculating the rotation
1116      * angles (see {@link #getOrientation}). If the rotation matrix is also used
1117      * for rendering, it may not need to be transformed, for instance if your
1118      * {@link android.app.Activity Activity} is running in landscape mode.
1119      * </ul>
1120      *
1121      * <p>
1122      * Since the resulting coordinate system is orthonormal, only two axes need
1123      * to be specified.
1124      *
1125      * @param inR
1126      *        the rotation matrix to be transformed. Usually it is the matrix
1127      *        returned by {@link #getRotationMatrix}.
1128      *
1129      * @param X
1130      *        defines the axis of the new cooridinate system that coincide with the X axis of the
1131      *        original coordinate system.
1132      *
1133      * @param Y
1134      *        defines the axis of the new cooridinate system that coincide with the Y axis of the
1135      *        original coordinate system.
1136      *
1137      * @param outR
1138      *        the transformed rotation matrix. inR and outR should not be the same
1139      *        array.
1140      *
1141      * @return <code>true</code> on success. <code>false</code> if the input
1142      *         parameters are incorrect, for instance if X and Y define the same
1143      *         axis. Or if inR and outR don't have the same length.
1144      *
1145      * @see #getRotationMatrix(float[], float[], float[], float[])
1146      */
1147 
remapCoordinateSystem(float[] inR, int X, int Y, float[] outR)1148     public static boolean remapCoordinateSystem(float[] inR, int X, int Y,
1149             float[] outR)
1150     {
1151         if (inR == outR) {
1152             final float[] temp = mTempMatrix;
1153             synchronized(temp) {
1154                 // we don't expect to have a lot of contention
1155                 if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
1156                     final int size = outR.length;
1157                     for (int i=0 ; i<size ; i++)
1158                         outR[i] = temp[i];
1159                     return true;
1160                 }
1161             }
1162         }
1163         return remapCoordinateSystemImpl(inR, X, Y, outR);
1164     }
1165 
remapCoordinateSystemImpl(float[] inR, int X, int Y, float[] outR)1166     private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y,
1167             float[] outR)
1168     {
1169         /*
1170          * X and Y define a rotation matrix 'r':
1171          *
1172          *  (X==1)?((X&0x80)?-1:1):0    (X==2)?((X&0x80)?-1:1):0    (X==3)?((X&0x80)?-1:1):0
1173          *  (Y==1)?((Y&0x80)?-1:1):0    (Y==2)?((Y&0x80)?-1:1):0    (Y==3)?((X&0x80)?-1:1):0
1174          *                              r[0] ^ r[1]
1175          *
1176          * where the 3rd line is the vector product of the first 2 lines
1177          *
1178          */
1179 
1180         final int length = outR.length;
1181         if (inR.length != length)
1182             return false;   // invalid parameter
1183         if ((X & 0x7C)!=0 || (Y & 0x7C)!=0)
1184             return false;   // invalid parameter
1185         if (((X & 0x3)==0) || ((Y & 0x3)==0))
1186             return false;   // no axis specified
1187         if ((X & 0x3) == (Y & 0x3))
1188             return false;   // same axis specified
1189 
1190         // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
1191         // this can be calculated by exclusive-or'ing X and Y; except for
1192         // the sign inversion (+/-) which is calculated below.
1193         int Z = X ^ Y;
1194 
1195         // extract the axis (remove the sign), offset in the range 0 to 2.
1196         final int x = (X & 0x3)-1;
1197         final int y = (Y & 0x3)-1;
1198         final int z = (Z & 0x3)-1;
1199 
1200         // compute the sign of Z (whether it needs to be inverted)
1201         final int axis_y = (z+1)%3;
1202         final int axis_z = (z+2)%3;
1203         if (((x^axis_y)|(y^axis_z)) != 0)
1204             Z ^= 0x80;
1205 
1206         final boolean sx = (X>=0x80);
1207         final boolean sy = (Y>=0x80);
1208         final boolean sz = (Z>=0x80);
1209 
1210         // Perform R * r, in avoiding actual muls and adds.
1211         final int rowLength = ((length==16)?4:3);
1212         for (int j=0 ; j<3 ; j++) {
1213             final int offset = j*rowLength;
1214             for (int i=0 ; i<3 ; i++) {
1215                 if (x==i)   outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0];
1216                 if (y==i)   outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1];
1217                 if (z==i)   outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2];
1218             }
1219         }
1220         if (length == 16) {
1221             outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
1222             outR[15] = 1;
1223         }
1224         return true;
1225     }
1226 
1227     /**
1228      * Computes the device's orientation based on the rotation matrix.
1229      * <p>
1230      * When it returns, the array values is filled with the result:
1231      * <ul>
1232      * <li>values[0]: <i>azimuth</i>, rotation around the -Z axis,
1233      *                i.e. the opposite direction of Z axis.</li>
1234      * <li>values[1]: <i>pitch</i>, rotation around the -X axis,
1235      *                i.e the opposite direction of X axis.</li>
1236      * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li>
1237      * </ul>
1238      * <p>
1239      * Applying these three intrinsic rotations in azimuth, pitch and roll order transforms
1240      * identity matrix to the rotation matrix given in input R.
1241      * All three angles above are in <b>radians</b> and <b>positive</b> in the
1242      * <b>counter-clockwise</b> direction. Range of output is: azimuth from -&pi; to &pi;,
1243      * pitch from -&pi;/2 to &pi;/2 and roll from -&pi; to &pi;.
1244      *
1245      * @param R
1246      *        rotation matrix see {@link #getRotationMatrix}.
1247      *
1248      * @param values
1249      *        an array of 3 floats to hold the result.
1250      *
1251      * @return The array values passed as argument.
1252      *
1253      * @see #getRotationMatrix(float[], float[], float[], float[])
1254      * @see GeomagneticField
1255      */
getOrientation(float[] R, float values[])1256     public static float[] getOrientation(float[] R, float values[]) {
1257         /*
1258          * 4x4 (length=16) case:
1259          *   /  R[ 0]   R[ 1]   R[ 2]   0  \
1260          *   |  R[ 4]   R[ 5]   R[ 6]   0  |
1261          *   |  R[ 8]   R[ 9]   R[10]   0  |
1262          *   \      0       0       0   1  /
1263          *
1264          * 3x3 (length=9) case:
1265          *   /  R[ 0]   R[ 1]   R[ 2]  \
1266          *   |  R[ 3]   R[ 4]   R[ 5]  |
1267          *   \  R[ 6]   R[ 7]   R[ 8]  /
1268          *
1269          */
1270         if (R.length == 9) {
1271             values[0] = (float)Math.atan2(R[1], R[4]);
1272             values[1] = (float)Math.asin(-R[7]);
1273             values[2] = (float)Math.atan2(-R[6], R[8]);
1274         } else {
1275             values[0] = (float)Math.atan2(R[1], R[5]);
1276             values[1] = (float)Math.asin(-R[9]);
1277             values[2] = (float)Math.atan2(-R[8], R[10]);
1278         }
1279 
1280         return values;
1281     }
1282 
1283     /**
1284      * Computes the Altitude in meters from the atmospheric pressure and the
1285      * pressure at sea level.
1286      * <p>
1287      * Typically the atmospheric pressure is read from a
1288      * {@link Sensor#TYPE_PRESSURE} sensor. The pressure at sea level must be
1289      * known, usually it can be retrieved from airport databases in the
1290      * vicinity. If unknown, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE}
1291      * as an approximation, but absolute altitudes won't be accurate.
1292      * </p>
1293      * <p>
1294      * To calculate altitude differences, you must calculate the difference
1295      * between the altitudes at both points. If you don't know the altitude
1296      * as sea level, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE} instead,
1297      * which will give good results considering the range of pressure typically
1298      * involved.
1299      * </p>
1300      * <p>
1301      * <code><ul>
1302      *  float altitude_difference =
1303      *      getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point2)
1304      *      - getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point1);
1305      * </ul></code>
1306      * </p>
1307      *
1308      * @param p0 pressure at sea level
1309      * @param p atmospheric pressure
1310      * @return Altitude in meters
1311      */
getAltitude(float p0, float p)1312     public static float getAltitude(float p0, float p) {
1313         final float coef = 1.0f / 5.255f;
1314         return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef));
1315     }
1316 
1317     /** Helper function to compute the angle change between two rotation matrices.
1318      *  Given a current rotation matrix (R) and a previous rotation matrix
1319      *  (prevR) computes the intrinsic rotation around the z, x, and y axes which
1320      *  transforms prevR to R.
1321      *  outputs a 3 element vector containing the z, x, and y angle
1322      *  change at indexes 0, 1, and 2 respectively.
1323      * <p> Each input matrix is either as a 3x3 or 4x4 row-major matrix
1324      * depending on the length of the passed array:
1325      * <p>If the array length is 9, then the array elements represent this matrix
1326      * <pre>
1327      *   /  R[ 0]   R[ 1]   R[ 2]   \
1328      *   |  R[ 3]   R[ 4]   R[ 5]   |
1329      *   \  R[ 6]   R[ 7]   R[ 8]   /
1330      *</pre>
1331      * <p>If the array length is 16, then the array elements represent this matrix
1332      * <pre>
1333      *   /  R[ 0]   R[ 1]   R[ 2]   R[ 3]  \
1334      *   |  R[ 4]   R[ 5]   R[ 6]   R[ 7]  |
1335      *   |  R[ 8]   R[ 9]   R[10]   R[11]  |
1336      *   \  R[12]   R[13]   R[14]   R[15]  /
1337      *</pre>
1338      *
1339      * See {@link #getOrientation} for more detailed definition of the output.
1340      *
1341      * @param R current rotation matrix
1342      * @param prevR previous rotation matrix
1343      * @param angleChange an an array of floats (z, x, and y) in which the angle change
1344      *        (in radians) is stored
1345      */
1346 
getAngleChange( float[] angleChange, float[] R, float[] prevR)1347     public static void getAngleChange( float[] angleChange, float[] R, float[] prevR) {
1348         float rd1=0,rd4=0, rd6=0,rd7=0, rd8=0;
1349         float ri0=0,ri1=0,ri2=0,ri3=0,ri4=0,ri5=0,ri6=0,ri7=0,ri8=0;
1350         float pri0=0, pri1=0, pri2=0, pri3=0, pri4=0, pri5=0, pri6=0, pri7=0, pri8=0;
1351 
1352         if(R.length == 9) {
1353             ri0 = R[0];
1354             ri1 = R[1];
1355             ri2 = R[2];
1356             ri3 = R[3];
1357             ri4 = R[4];
1358             ri5 = R[5];
1359             ri6 = R[6];
1360             ri7 = R[7];
1361             ri8 = R[8];
1362         } else if(R.length == 16) {
1363             ri0 = R[0];
1364             ri1 = R[1];
1365             ri2 = R[2];
1366             ri3 = R[4];
1367             ri4 = R[5];
1368             ri5 = R[6];
1369             ri6 = R[8];
1370             ri7 = R[9];
1371             ri8 = R[10];
1372         }
1373 
1374         if(prevR.length == 9) {
1375             pri0 = prevR[0];
1376             pri1 = prevR[1];
1377             pri2 = prevR[2];
1378             pri3 = prevR[3];
1379             pri4 = prevR[4];
1380             pri5 = prevR[5];
1381             pri6 = prevR[6];
1382             pri7 = prevR[7];
1383             pri8 = prevR[8];
1384         } else if(prevR.length == 16) {
1385             pri0 = prevR[0];
1386             pri1 = prevR[1];
1387             pri2 = prevR[2];
1388             pri3 = prevR[4];
1389             pri4 = prevR[5];
1390             pri5 = prevR[6];
1391             pri6 = prevR[8];
1392             pri7 = prevR[9];
1393             pri8 = prevR[10];
1394         }
1395 
1396         // calculate the parts of the rotation difference matrix we need
1397         // rd[i][j] = pri[0][i] * ri[0][j] + pri[1][i] * ri[1][j] + pri[2][i] * ri[2][j];
1398 
1399         rd1 = pri0 * ri1 + pri3 * ri4 + pri6 * ri7; //rd[0][1]
1400         rd4 = pri1 * ri1 + pri4 * ri4 + pri7 * ri7; //rd[1][1]
1401         rd6 = pri2 * ri0 + pri5 * ri3 + pri8 * ri6; //rd[2][0]
1402         rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1]
1403         rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2]
1404 
1405         angleChange[0] = (float)Math.atan2(rd1, rd4);
1406         angleChange[1] = (float)Math.asin(-rd7);
1407         angleChange[2] = (float)Math.atan2(-rd6, rd8);
1408 
1409     }
1410 
1411     /** Helper function to convert a rotation vector to a rotation matrix.
1412      *  Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a
1413      *  9  or 16 element rotation matrix in the array R.  R must have length 9 or 16.
1414      *  If R.length == 9, the following matrix is returned:
1415      * <pre>
1416      *   /  R[ 0]   R[ 1]   R[ 2]   \
1417      *   |  R[ 3]   R[ 4]   R[ 5]   |
1418      *   \  R[ 6]   R[ 7]   R[ 8]   /
1419      *</pre>
1420      * If R.length == 16, the following matrix is returned:
1421      * <pre>
1422      *   /  R[ 0]   R[ 1]   R[ 2]   0  \
1423      *   |  R[ 4]   R[ 5]   R[ 6]   0  |
1424      *   |  R[ 8]   R[ 9]   R[10]   0  |
1425      *   \  0       0       0       1  /
1426      *</pre>
1427      *  @param rotationVector the rotation vector to convert
1428      *  @param R an array of floats in which to store the rotation matrix
1429      */
getRotationMatrixFromVector(float[] R, float[] rotationVector)1430     public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) {
1431 
1432         float q0;
1433         float q1 = rotationVector[0];
1434         float q2 = rotationVector[1];
1435         float q3 = rotationVector[2];
1436 
1437         if (rotationVector.length >= 4) {
1438             q0 = rotationVector[3];
1439         } else {
1440             q0 = 1 - q1*q1 - q2*q2 - q3*q3;
1441             q0 = (q0 > 0) ? (float)Math.sqrt(q0) : 0;
1442         }
1443 
1444         float sq_q1 = 2 * q1 * q1;
1445         float sq_q2 = 2 * q2 * q2;
1446         float sq_q3 = 2 * q3 * q3;
1447         float q1_q2 = 2 * q1 * q2;
1448         float q3_q0 = 2 * q3 * q0;
1449         float q1_q3 = 2 * q1 * q3;
1450         float q2_q0 = 2 * q2 * q0;
1451         float q2_q3 = 2 * q2 * q3;
1452         float q1_q0 = 2 * q1 * q0;
1453 
1454         if(R.length == 9) {
1455             R[0] = 1 - sq_q2 - sq_q3;
1456             R[1] = q1_q2 - q3_q0;
1457             R[2] = q1_q3 + q2_q0;
1458 
1459             R[3] = q1_q2 + q3_q0;
1460             R[4] = 1 - sq_q1 - sq_q3;
1461             R[5] = q2_q3 - q1_q0;
1462 
1463             R[6] = q1_q3 - q2_q0;
1464             R[7] = q2_q3 + q1_q0;
1465             R[8] = 1 - sq_q1 - sq_q2;
1466         } else if (R.length == 16) {
1467             R[0] = 1 - sq_q2 - sq_q3;
1468             R[1] = q1_q2 - q3_q0;
1469             R[2] = q1_q3 + q2_q0;
1470             R[3] = 0.0f;
1471 
1472             R[4] = q1_q2 + q3_q0;
1473             R[5] = 1 - sq_q1 - sq_q3;
1474             R[6] = q2_q3 - q1_q0;
1475             R[7] = 0.0f;
1476 
1477             R[8] = q1_q3 - q2_q0;
1478             R[9] = q2_q3 + q1_q0;
1479             R[10] = 1 - sq_q1 - sq_q2;
1480             R[11] = 0.0f;
1481 
1482             R[12] = R[13] = R[14] = 0.0f;
1483             R[15] = 1.0f;
1484         }
1485     }
1486 
1487     /** Helper function to convert a rotation vector to a normalized quaternion.
1488      *  Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a normalized
1489      *  quaternion in the array Q.  The quaternion is stored as [w, x, y, z]
1490      *  @param rv the rotation vector to convert
1491      *  @param Q an array of floats in which to store the computed quaternion
1492      */
getQuaternionFromVector(float[] Q, float[] rv)1493     public static void getQuaternionFromVector(float[] Q, float[] rv) {
1494         if (rv.length >= 4) {
1495             Q[0] = rv[3];
1496         } else {
1497             Q[0] = 1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2];
1498             Q[0] = (Q[0] > 0) ? (float)Math.sqrt(Q[0]) : 0;
1499         }
1500         Q[1] = rv[0];
1501         Q[2] = rv[1];
1502         Q[3] = rv[2];
1503     }
1504 
1505     /**
1506      * Requests receiving trigger events for a trigger sensor.
1507      *
1508      * <p>
1509      * When the sensor detects a trigger event condition, such as significant motion in
1510      * the case of the {@link Sensor#TYPE_SIGNIFICANT_MOTION}, the provided trigger listener
1511      * will be invoked once and then its request to receive trigger events will be canceled.
1512      * To continue receiving trigger events, the application must request to receive trigger
1513      * events again.
1514      * </p>
1515      *
1516      * @param listener The listener on which the
1517      *        {@link TriggerEventListener#onTrigger(TriggerEvent)} will be delivered.
1518      * @param sensor The sensor to be enabled.
1519      *
1520      * @return true if the sensor was successfully enabled.
1521      *
1522      * @throws IllegalArgumentException when sensor is null or not a trigger sensor.
1523      */
requestTriggerSensor(TriggerEventListener listener, Sensor sensor)1524     public boolean requestTriggerSensor(TriggerEventListener listener, Sensor sensor) {
1525         return requestTriggerSensorImpl(listener, sensor);
1526     }
1527 
1528     /**
1529      * @hide
1530      */
requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor)1531     protected abstract boolean requestTriggerSensorImpl(TriggerEventListener listener,
1532             Sensor sensor);
1533 
1534     /**
1535      * Cancels receiving trigger events for a trigger sensor.
1536      *
1537      * <p>
1538      * Note that a Trigger sensor will be auto disabled if
1539      * {@link TriggerEventListener#onTrigger(TriggerEvent)} has triggered.
1540      * This method is provided in case the user wants to explicitly cancel the request
1541      * to receive trigger events.
1542      * </p>
1543      *
1544      * @param listener The listener on which the
1545      *        {@link TriggerEventListener#onTrigger(TriggerEvent)}
1546      *        is delivered.It should be the same as the one used
1547      *        in {@link #requestTriggerSensor(TriggerEventListener, Sensor)}
1548      * @param sensor The sensor for which the trigger request should be canceled.
1549      *        If null, it cancels receiving trigger for all sensors associated
1550      *        with the listener.
1551      *
1552      * @return true if successfully canceled.
1553      *
1554      * @throws IllegalArgumentException when sensor is a trigger sensor.
1555      */
cancelTriggerSensor(TriggerEventListener listener, Sensor sensor)1556     public boolean cancelTriggerSensor(TriggerEventListener listener, Sensor sensor) {
1557         return cancelTriggerSensorImpl(listener, sensor, true);
1558     }
1559 
1560     /**
1561      * @hide
1562      */
cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor, boolean disable)1563     protected abstract boolean cancelTriggerSensorImpl(TriggerEventListener listener,
1564             Sensor sensor, boolean disable);
1565 
1566 
1567     /**
1568      * For testing purposes only. Not for third party applications.
1569      *
1570      * Initialize data injection mode and create a client for data injection. SensorService should
1571      * already be operating in DATA_INJECTION mode for this call succeed. To set SensorService into
1572      * DATA_INJECTION mode "adb shell dumpsys sensorservice data_injection" needs to be called
1573      * through adb. Typically this is done using a host side test.  This mode is expected to be used
1574      * only for testing purposes. If the HAL is set to data injection mode, it will ignore the input
1575      * from physical sensors and read sensor data that is injected from the test application. This
1576      * mode is used for testing vendor implementations for various algorithms like Rotation Vector,
1577      * Significant Motion, Step Counter etc. Not all HALs support DATA_INJECTION. This method will
1578      * fail in those cases. Once this method succeeds, the test can call
1579      * {@link injectSensorData(Sensor, float[], int, long)} to inject sensor data into the HAL.
1580      *
1581      * @param enable True to initialize a client in DATA_INJECTION mode.
1582      *               False to clean up the native resources.
1583      *
1584      * @return true if the HAL supports data injection and false
1585      *         otherwise.
1586      * @hide
1587      */
1588     @SystemApi
initDataInjection(boolean enable)1589     public boolean initDataInjection(boolean enable) {
1590           return initDataInjectionImpl(enable);
1591     }
1592 
1593     /**
1594      * @hide
1595      */
initDataInjectionImpl(boolean enable)1596     protected abstract boolean initDataInjectionImpl(boolean enable);
1597 
1598     /**
1599      * For testing purposes only. Not for third party applications.
1600      *
1601      * This method is used to inject raw sensor data into the HAL.  Call {@link
1602      * initDataInjection(boolean)} before this method to set the HAL in data injection mode. This
1603      * method should be called only if a previous call to initDataInjection has been successful and
1604      * the HAL and SensorService are already opreating in data injection mode.
1605      *
1606      * @param sensor The sensor to inject.
1607      * @param values Sensor values to inject. The length of this
1608      *               array must be exactly equal to the number of
1609      *               values reported by the sensor type.
1610      * @param accuracy Accuracy of the sensor.
1611      * @param timestamp Sensor timestamp associated with the event.
1612      *
1613      * @return boolean True if the data injection succeeds, false
1614      *         otherwise.
1615      * @throws IllegalArgumentException when the sensor is null,
1616      *         data injection is not supported by the sensor, values
1617      *         are null, incorrect number of values for the sensor,
1618      *         sensor accuracy is incorrect or timestamps are
1619      *         invalid.
1620      * @hide
1621      */
1622     @SystemApi
injectSensorData(Sensor sensor, float[] values, int accuracy, long timestamp)1623     public boolean injectSensorData(Sensor sensor, float[] values, int accuracy,
1624                 long timestamp) {
1625         if (sensor == null) {
1626             throw new IllegalArgumentException("sensor cannot be null");
1627         }
1628         if (!sensor.isDataInjectionSupported()) {
1629             throw new IllegalArgumentException("sensor does not support data injection");
1630         }
1631         if (values == null) {
1632             throw new IllegalArgumentException("sensor data cannot be null");
1633         }
1634         int expectedNumValues = Sensor.getMaxLengthValuesArray(sensor, Build.VERSION_CODES.M);
1635         if (values.length != expectedNumValues) {
1636             throw new  IllegalArgumentException ("Wrong number of values for sensor " +
1637                     sensor.getName() + " actual=" + values.length + " expected=" +
1638                                                   expectedNumValues);
1639         }
1640         if (accuracy < SENSOR_STATUS_NO_CONTACT || accuracy > SENSOR_STATUS_ACCURACY_HIGH) {
1641             throw new IllegalArgumentException("Invalid sensor accuracy");
1642         }
1643         if (timestamp <= 0) {
1644             throw new IllegalArgumentException("Negative or zero sensor timestamp");
1645         }
1646         return injectSensorDataImpl(sensor, values, accuracy, timestamp);
1647     }
1648 
1649     /**
1650      * @hide
1651      */
injectSensorDataImpl(Sensor sensor, float[] values, int accuracy, long timestamp)1652     protected abstract boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
1653                 long timestamp);
1654 
getLegacySensorManager()1655     private LegacySensorManager getLegacySensorManager() {
1656         synchronized (mSensorListByType) {
1657             if (mLegacySensorManager == null) {
1658                 Log.i(TAG, "This application is using deprecated SensorManager API which will "
1659                         + "be removed someday.  Please consider switching to the new API.");
1660                 mLegacySensorManager = new LegacySensorManager(this);
1661             }
1662             return mLegacySensorManager;
1663         }
1664     }
1665 
getDelay(int rate)1666     private static int getDelay(int rate) {
1667         int delay = -1;
1668         switch (rate) {
1669             case SENSOR_DELAY_FASTEST:
1670                 delay = 0;
1671                 break;
1672             case SENSOR_DELAY_GAME:
1673                 delay = 20000;
1674                 break;
1675             case SENSOR_DELAY_UI:
1676                 delay = 66667;
1677                 break;
1678             case SENSOR_DELAY_NORMAL:
1679                 delay = 200000;
1680                 break;
1681             default:
1682                 delay = rate;
1683                 break;
1684         }
1685         return delay;
1686     }
1687 }
1688