blob: 5684aa5cb6fcf56d12ecc58f5c093fbe666e4688 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package android.hardware;
18
Aravind Akella18ebf732b2015-04-20 17:39:51 -070019import android.annotation.SystemApi;
20import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import android.os.Handler;
Jeff Brown4481d9c2012-04-16 16:14:44 -070022import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.util.SparseArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import java.util.ArrayList;
26import java.util.Collections;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import java.util.List;
28
29/**
Mathias Agopian43c87e42010-08-25 14:35:54 -070030 * <p>
Mathias Agopian74cde2c2010-06-16 18:55:46 -070031 * 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}.
Mathias Agopian43c87e42010-08-25 14:35:54 -070036 * </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>
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -080043 * <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>
Mathias Agopian0f791a72010-06-22 21:55:01 -070048 * <pre class="prettyprint">
Greg Kaiserac823732016-02-26 16:37:01 -080049 * public class SensorActivity extends Activity implements SensorEventListener {
Mathias Agopian0f791a72010-06-22 21:55:01 -070050 * 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);
Mathias Agopian43c87e42010-08-25 14:35:54 -070056 * }
57 *
58 * protected void onResume() {
59 * super.onResume();
Mathias Agopian0f791a72010-06-22 21:55:01 -070060 * mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
61 * }
62 *
Mathias Agopian43c87e42010-08-25 14:35:54 -070063 * protected void onPause() {
64 * super.onPause();
65 * mSensorManager.unregisterListener(this);
66 * }
67 *
Mathias Agopian0f791a72010-06-22 21:55:01 -070068 * public void onAccuracyChanged(Sensor sensor, int accuracy) {
69 * }
70 *
Mathias Agopian43c87e42010-08-25 14:35:54 -070071 * public void onSensorChanged(SensorEvent event) {
Mathias Agopian0f791a72010-06-22 21:55:01 -070072 * }
73 * }
74 * </pre>
75 *
76 * @see SensorEventListener
77 * @see SensorEvent
78 * @see Sensor
79 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 */
Jeff Brown25157e42012-04-16 12:13:05 -070081public abstract class SensorManager {
Jeff Brown4481d9c2012-04-16 16:14:44 -070082 /** @hide */
83 protected static final String TAG = "SensorManager";
84
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 private static final float[] mTempMatrix = new float[16];
86
Jeff Brown25157e42012-04-16 12:13:05 -070087 // Cached lists of sensors by type. Guarded by mSensorListByType.
88 private final SparseArray<List<Sensor>> mSensorListByType =
89 new SparseArray<List<Sensor>>();
90
Jeff Brown4481d9c2012-04-16 16:14:44 -070091 // Legacy sensor manager implementation. Guarded by mSensorListByType during initialization.
92 private LegacySensorManager mLegacySensorManager;
93
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094 /* NOTE: sensor IDs must be a power of 2 */
95
96 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -070097 * A constant describing an orientation sensor. See
98 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -070099 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
101 */
102 @Deprecated
103 public static final int SENSOR_ORIENTATION = 1 << 0;
104
105 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700106 * A constant describing an accelerometer. See
107 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700108 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
110 */
111 @Deprecated
112 public static final int SENSOR_ACCELEROMETER = 1 << 1;
113
114 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700115 * A constant describing a temperature sensor See
116 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700117 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
119 */
120 @Deprecated
121 public static final int SENSOR_TEMPERATURE = 1 << 2;
122
123 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700124 * A constant describing a magnetic sensor See
125 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700126 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
128 */
129 @Deprecated
130 public static final int SENSOR_MAGNETIC_FIELD = 1 << 3;
131
132 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700133 * A constant describing an ambient light sensor See
134 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700135 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
137 */
138 @Deprecated
139 public static final int SENSOR_LIGHT = 1 << 4;
140
141 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700142 * A constant describing a proximity sensor See
143 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700144 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
146 */
147 @Deprecated
148 public static final int SENSOR_PROXIMITY = 1 << 5;
149
150 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700151 * A constant describing a Tricorder See
152 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700153 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
155 */
156 @Deprecated
157 public static final int SENSOR_TRICORDER = 1 << 6;
158
159 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700160 * A constant describing an orientation sensor. See
161 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700162 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
164 */
165 @Deprecated
166 public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
167
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700168 /**
169 * A constant that includes all sensors
Mathias Agopian0f791a72010-06-22 21:55:01 -0700170 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700171 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
172 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 @Deprecated
174 public static final int SENSOR_ALL = 0x7F;
175
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700176 /**
177 * Smallest sensor ID
Mathias Agopian0f791a72010-06-22 21:55:01 -0700178 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700179 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
180 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181 @Deprecated
182 public static final int SENSOR_MIN = SENSOR_ORIENTATION;
183
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700184 /**
185 * Largest sensor ID
Mathias Agopian0f791a72010-06-22 21:55:01 -0700186 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700187 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
188 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 @Deprecated
190 public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1);
191
192
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700193 /**
194 * Index of the X value in the array returned by
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700195 * {@link android.hardware.SensorListener#onSensorChanged}
Mathias Agopian0f791a72010-06-22 21:55:01 -0700196 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700197 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
198 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 @Deprecated
200 public static final int DATA_X = 0;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700201
202 /**
203 * Index of the Y value in the array returned by
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700204 * {@link android.hardware.SensorListener#onSensorChanged}
Mathias Agopian0f791a72010-06-22 21:55:01 -0700205 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700206 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
207 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 @Deprecated
209 public static final int DATA_Y = 1;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700210
211 /**
212 * Index of the Z value in the array returned by
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700213 * {@link android.hardware.SensorListener#onSensorChanged}
Mathias Agopian0f791a72010-06-22 21:55:01 -0700214 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700215 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
216 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 @Deprecated
218 public static final int DATA_Z = 2;
219
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700220 /**
221 * Offset to the untransformed values in the array returned by
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700222 * {@link android.hardware.SensorListener#onSensorChanged}
Mathias Agopian0f791a72010-06-22 21:55:01 -0700223 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700224 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
225 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 @Deprecated
227 public static final int RAW_DATA_INDEX = 3;
228
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700229 /**
230 * Index of the untransformed X value in the array returned by
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700231 * {@link android.hardware.SensorListener#onSensorChanged}
Mathias Agopian0f791a72010-06-22 21:55:01 -0700232 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700233 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
234 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 @Deprecated
236 public static final int RAW_DATA_X = 3;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700237
238 /**
239 * Index of the untransformed Y value in the array returned by
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700240 * {@link android.hardware.SensorListener#onSensorChanged}
Mathias Agopian0f791a72010-06-22 21:55:01 -0700241 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700242 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
243 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 @Deprecated
245 public static final int RAW_DATA_Y = 4;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700246
247 /**
248 * Index of the untransformed Z value in the array returned by
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700249 * {@link android.hardware.SensorListener#onSensorChanged}
Mathias Agopian0f791a72010-06-22 21:55:01 -0700250 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700251 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
252 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 @Deprecated
254 public static final int RAW_DATA_Z = 5;
255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 /** Standard gravity (g) on Earth. This value is equivalent to 1G */
257 public static final float STANDARD_GRAVITY = 9.80665f;
258
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700259 /** Sun's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 public static final float GRAVITY_SUN = 275.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700261 /** Mercury's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262 public static final float GRAVITY_MERCURY = 3.70f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700263 /** Venus' gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 public static final float GRAVITY_VENUS = 8.87f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700265 /** Earth's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 public static final float GRAVITY_EARTH = 9.80665f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700267 /** The Moon's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 public static final float GRAVITY_MOON = 1.6f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700269 /** Mars' gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 public static final float GRAVITY_MARS = 3.71f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700271 /** Jupiter's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 public static final float GRAVITY_JUPITER = 23.12f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700273 /** Saturn's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 public static final float GRAVITY_SATURN = 8.96f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700275 /** Uranus' gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 public static final float GRAVITY_URANUS = 8.69f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700277 /** Neptune's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 public static final float GRAVITY_NEPTUNE = 11.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700279 /** Pluto's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 public static final float GRAVITY_PLUTO = 0.6f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700281 /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 public static final float GRAVITY_DEATH_STAR_I = 0.000000353036145f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700283 /** Gravity on the island */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 /** Minimum magnetic field on Earth's surface */
290 public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;
291
Mathias Agopian0f791a72010-06-22 21:55:01 -0700292
Mathias Agopian04d7e83e2010-07-29 17:59:58 -0700293 /** Standard atmosphere, or average sea-level pressure in hPa (millibar) */
294 public static final float PRESSURE_STANDARD_ATMOSPHERE = 1013.25f;
295
296
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700297 /** Maximum luminance of sunlight in lux */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700299 /** luminance of sunlight in lux */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 public static final float LIGHT_SUNLIGHT = 110000.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700301 /** luminance in shade in lux */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 public static final float LIGHT_SHADE = 20000.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700303 /** luminance under an overcast sky in lux */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 public static final float LIGHT_OVERCAST = 10000.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700305 /** luminance at sunrise in lux */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 public static final float LIGHT_SUNRISE = 400.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700307 /** luminance under a cloudy sky in lux */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 public static final float LIGHT_CLOUDY = 100.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700309 /** luminance at night with full moon in lux */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 public static final float LIGHT_FULLMOON = 0.25f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700311 /** luminance at night with no moon in lux*/
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 public static final float LIGHT_NO_MOON = 0.001f;
313
Mathias Agopian0f791a72010-06-22 21:55:01 -0700314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 /** 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
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700325 /**
Etienne Le Grandaf805102014-05-16 12:21:41 -0700326 * 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 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700333 * The values returned by this sensor cannot be trusted, calibration is
334 * needed or the environment doesn't allow readings
335 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 public static final int SENSOR_STATUS_UNRELIABLE = 0;
337
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700338 /**
339 * This sensor is reporting data with low accuracy, calibration with the
340 * environment is needed
341 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
343
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700344 /**
345 * This sensor is reporting data with an average level of accuracy,
346 * calibration with the environment may improve the readings
347 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366
367 /**
368 * {@hide}
369 */
Jeff Brown25157e42012-04-16 12:13:05 -0700370 public SensorManager() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 }
372
Jeff Brown25157e42012-04-16 12:13:05 -0700373 /**
374 * Gets the full list of sensors that are available.
375 * @hide
376 */
377 protected abstract List<Sensor> getFullSensorList();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700379 /**
Peng Xua35b5532016-01-20 00:05:45 -0800380 * Gets the full list of dynamic sensors that are available.
381 * @hide
382 */
383 protected abstract List<Sensor> getFullDynamicSensorList();
384
385 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700386 * @return available sensors.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 * @deprecated This method is deprecated, use
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700388 * {@link SensorManager#getSensorList(int)} instead
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 */
390 @Deprecated
391 public int getSensors() {
Jeff Brown4481d9c2012-04-16 16:14:44 -0700392 return getLegacySensorManager().getSensors();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393 }
394
395 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700396 * Use this method to get the list of available sensors of a certain type.
397 * Make multiple calls to get sensors of different types or use
398 * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the
399 * sensors.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700400 *
Aravind Akella0288ca62014-07-28 14:53:44 -0700401 * <p class="note">
402 * NOTE: Both wake-up and non wake-up sensors matching the given type are
403 * returned. Check {@link Sensor#isWakeUpSensor()} to know the wake-up properties
404 * of the returned {@link Sensor}.
405 * </p>
406 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700407 * @param type
408 * of sensors requested
Mathias Agopian0f791a72010-06-22 21:55:01 -0700409 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 * @return a list of sensors matching the asked type.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700411 *
412 * @see #getDefaultSensor(int)
413 * @see Sensor
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 */
415 public List<Sensor> getSensorList(int type) {
416 // cache the returned lists the first time
417 List<Sensor> list;
Jeff Brown25157e42012-04-16 12:13:05 -0700418 final List<Sensor> fullList = getFullSensorList();
419 synchronized (mSensorListByType) {
420 list = mSensorListByType.get(type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 if (list == null) {
422 if (type == Sensor.TYPE_ALL) {
423 list = fullList;
424 } else {
425 list = new ArrayList<Sensor>();
426 for (Sensor i : fullList) {
427 if (i.getType() == type)
428 list.add(i);
429 }
430 }
431 list = Collections.unmodifiableList(list);
Jeff Brown25157e42012-04-16 12:13:05 -0700432 mSensorListByType.append(type, list);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 }
434 }
435 return list;
436 }
437
438 /**
Peng Xua35b5532016-01-20 00:05:45 -0800439 * Use this method to get a list of available dynamic sensors of a certain type.
440 * Make multiple calls to get sensors of different types or use
441 * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all dynamic sensors.
442 *
443 * <p class="note">
444 * NOTE: Both wake-up and non wake-up sensors matching the given type are
445 * returned. Check {@link Sensor#isWakeUpSensor()} to know the wake-up properties
446 * of the returned {@link Sensor}.
447 * </p>
448 *
449 * @param type of sensors requested
450 *
451 * @return a list of dynamic sensors matching the requested type.
452 *
453 * @see Sensor
454 */
455 public List<Sensor> getDynamicSensorList(int type) {
456 // cache the returned lists the first time
457 final List<Sensor> fullList = getFullDynamicSensorList();
458 if (type == Sensor.TYPE_ALL) {
459 return Collections.unmodifiableList(fullList);
460 } else {
461 List<Sensor> list = new ArrayList();
462 for (Sensor i : fullList) {
463 if (i.getType() == type)
464 list.add(i);
465 }
466 return Collections.unmodifiableList(list);
467 }
468 }
469
470 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700471 * Use this method to get the default sensor for a given type. Note that the
472 * returned sensor could be a composite sensor, and its data could be
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 * averaged or filtered. If you need to access the raw sensors use
474 * {@link SensorManager#getSensorList(int) getSensorList}.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700475 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700476 * @param type
Etienne Le Grandaf805102014-05-16 12:21:41 -0700477 * of sensors requested
Mathias Agopian0f791a72010-06-22 21:55:01 -0700478 *
Etienne Le Grandaf805102014-05-16 12:21:41 -0700479 * @return the default sensor matching the requested type if one exists and the application
480 * has the necessary permissions, or null otherwise.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700481 *
482 * @see #getSensorList(int)
483 * @see Sensor
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 */
485 public Sensor getDefaultSensor(int type) {
486 // TODO: need to be smarter, for now, just return the 1st sensor
487 List<Sensor> l = getSensorList(type);
Aravind Akella0288ca62014-07-28 14:53:44 -0700488 boolean wakeUpSensor = false;
489 // For the following sensor types, return a wake-up sensor. These types are by default
490 // defined as wake-up sensors. For the rest of the SDK defined sensor types return a
491 // non_wake-up version.
492 if (type == Sensor.TYPE_PROXIMITY || type == Sensor.TYPE_SIGNIFICANT_MOTION ||
493 type == Sensor.TYPE_TILT_DETECTOR || type == Sensor.TYPE_WAKE_GESTURE ||
Nick Vaccarof5021f62015-01-23 15:09:45 -0800494 type == Sensor.TYPE_GLANCE_GESTURE || type == Sensor.TYPE_PICK_UP_GESTURE ||
495 type == Sensor.TYPE_WRIST_TILT_GESTURE) {
Aravind Akella0288ca62014-07-28 14:53:44 -0700496 wakeUpSensor = true;
497 }
498
499 for (Sensor sensor : l) {
500 if (sensor.isWakeUpSensor() == wakeUpSensor) return sensor;
501 }
502 return null;
503 }
504
505 /**
506 * Return a Sensor with the given type and wakeUp properties. If multiple sensors of this
507 * type exist, any one of them may be returned.
508 * <p>
509 * For example,
510 * <ul>
511 * <li>getDefaultSensor({@link Sensor#TYPE_ACCELEROMETER}, true) returns a wake-up accelerometer
512 * sensor if it exists. </li>
513 * <li>getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, false) returns a non wake-up proximity
514 * sensor if it exists. </li>
515 * <li>getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, true) returns a wake-up proximity sensor
516 * which is the same as the Sensor returned by {@link #getDefaultSensor(int)}. </li>
517 * </ul>
518 * </p>
519 * <p class="note">
520 * Note: Sensors like {@link Sensor#TYPE_PROXIMITY} and {@link Sensor#TYPE_SIGNIFICANT_MOTION}
521 * are declared as wake-up sensors by default.
522 * </p>
523 * @param type
524 * type of sensor requested
525 * @param wakeUp
526 * flag to indicate whether the Sensor is a wake-up or non wake-up sensor.
527 * @return the default sensor matching the requested type and wakeUp properties if one exists
528 * and the application has the necessary permissions, or null otherwise.
529 * @see Sensor#isWakeUpSensor()
530 */
531 public Sensor getDefaultSensor(int type, boolean wakeUp) {
532 List<Sensor> l = getSensorList(type);
533 for (Sensor sensor : l) {
534 if (sensor.isWakeUpSensor() == wakeUp)
535 return sensor;
536 }
537 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 }
539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 /**
541 * Registers a listener for given sensors.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700542 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 * @deprecated This method is deprecated, use
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700544 * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
545 * instead.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700546 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700547 * @param listener
548 * sensor listener object
Mathias Agopian0f791a72010-06-22 21:55:01 -0700549 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700550 * @param sensors
551 * a bit masks of the sensors to register to
Mathias Agopian0f791a72010-06-22 21:55:01 -0700552 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700553 * @return <code>true</code> if the sensor is supported and successfully
554 * enabled
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 */
556 @Deprecated
557 public boolean registerListener(SensorListener listener, int sensors) {
558 return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
559 }
560
561 /**
562 * Registers a SensorListener for given sensors.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700563 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564 * @deprecated This method is deprecated, use
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700565 * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
566 * instead.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700567 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700568 * @param listener
569 * sensor listener object
Mathias Agopian0f791a72010-06-22 21:55:01 -0700570 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700571 * @param sensors
572 * a bit masks of the sensors to register to
Mathias Agopian0f791a72010-06-22 21:55:01 -0700573 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700574 * @param rate
575 * rate of events. This is only a hint to the system. events may be
576 * received faster or slower than the specified rate. Usually events
577 * are received faster. The value must be one of
578 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
579 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700580 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700581 * @return <code>true</code> if the sensor is supported and successfully
582 * enabled
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 */
584 @Deprecated
585 public boolean registerListener(SensorListener listener, int sensors, int rate) {
Jeff Brown4481d9c2012-04-16 16:14:44 -0700586 return getLegacySensorManager().registerListener(listener, sensors, rate);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 }
588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 /**
590 * Unregisters a listener for all sensors.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700591 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800592 * @deprecated This method is deprecated, use
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700593 * {@link SensorManager#unregisterListener(SensorEventListener)}
594 * instead.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700595 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700596 * @param listener
597 * a SensorListener object
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 */
599 @Deprecated
600 public void unregisterListener(SensorListener listener) {
601 unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
602 }
603
Jeff Brown4481d9c2012-04-16 16:14:44 -0700604 /**
605 * Unregisters a listener for the sensors with which it is registered.
606 *
607 * @deprecated This method is deprecated, use
608 * {@link SensorManager#unregisterListener(SensorEventListener, Sensor)}
609 * instead.
610 *
611 * @param listener
612 * a SensorListener object
613 *
614 * @param sensors
615 * a bit masks of the sensors to unregister from
616 */
617 @Deprecated
618 public void unregisterListener(SensorListener listener, int sensors) {
619 getLegacySensorManager().unregisterListener(listener, sensors);
Jeff Brown25157e42012-04-16 12:13:05 -0700620 }
621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800622 /**
623 * Unregisters a listener for the sensors with which it is registered.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700624 *
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800625 * <p class="note"></p>
626 * Note: Don't use this method with a one shot trigger sensor such as
627 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}.
628 * Use {@link #cancelTriggerSensor(TriggerEventListener, Sensor)} instead.
629 * </p>
630 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700631 * @param listener
632 * a SensorEventListener object
Mathias Agopian0f791a72010-06-22 21:55:01 -0700633 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700634 * @param sensor
635 * the sensor to unregister from
Mathias Agopian0f791a72010-06-22 21:55:01 -0700636 *
637 * @see #unregisterListener(SensorEventListener)
638 * @see #registerListener(SensorEventListener, Sensor, int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800639 */
640 public void unregisterListener(SensorEventListener listener, Sensor sensor) {
Jeff Brown25157e42012-04-16 12:13:05 -0700641 if (listener == null || sensor == null) {
642 return;
643 }
644
645 unregisterListenerImpl(listener, sensor);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 }
647
648 /**
649 * Unregisters a listener for all sensors.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700650 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700651 * @param listener
652 * a SensorListener object
Mathias Agopian0f791a72010-06-22 21:55:01 -0700653 *
654 * @see #unregisterListener(SensorEventListener, Sensor)
655 * @see #registerListener(SensorEventListener, Sensor, int)
656 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800657 */
658 public void unregisterListener(SensorEventListener listener) {
Jeff Brown25157e42012-04-16 12:13:05 -0700659 if (listener == null) {
660 return;
661 }
662
663 unregisterListenerImpl(listener, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664 }
665
Jeff Brown25157e42012-04-16 12:13:05 -0700666 /** @hide */
667 protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor sensor);
668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669 /**
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700670 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
671 * sensor at the given sampling frequency.
672 * <p>
673 * The events will be delivered to the provided {@code SensorEventListener} as soon as they are
674 * available. To reduce the power consumption, applications can use
675 * {@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a
676 * positive non-zero maximum reporting latency.
677 * </p>
678 * <p>
679 * In the case of non-wake-up sensors, the events are only delivered while the Application
680 * Processor (AP) is not in suspend mode. See {@link Sensor#isWakeUpSensor()} for more details.
681 * To ensure delivery of events from non-wake-up sensors even when the screen is OFF, the
682 * application registering to the sensor must hold a partial wake-lock to keep the AP awake,
683 * otherwise some events might be lost while the AP is asleep. Note that although events might
684 * be lost while the AP is asleep, the sensor will still consume power if it is not explicitly
685 * deactivated by the application. Applications must unregister their {@code
686 * SensorEventListener}s in their activity's {@code onPause()} method to avoid consuming power
687 * while the device is inactive. See {@link #registerListener(SensorEventListener, Sensor, int,
688 * int)} for more details on hardware FIFO (queueing) capabilities and when some sensor events
689 * might be lost.
690 * </p>
691 * <p>
692 * In the case of wake-up sensors, each event generated by the sensor will cause the AP to
693 * wake-up, ensuring that each event can be delivered. Because of this, registering to a wake-up
694 * sensor has very significant power implications. Call {@link Sensor#isWakeUpSensor()} to check
695 * whether a sensor is a wake-up sensor. See
696 * {@link #registerListener(SensorEventListener, Sensor, int, int)} for information on how to
697 * reduce the power impact of registering to wake-up sensors.
698 * </p>
699 * <p class="note">
700 * Note: Don't use this method with one-shot trigger sensors such as
701 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use
702 * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. Use
703 * {@link Sensor#getReportingMode()} to obtain the reporting mode of a given sensor.
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800704 * </p>
705 *
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700706 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object.
707 * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
708 * @param samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are
709 * delivered at. This is only a hint to the system. Events may be received faster or
710 * slower than the specified rate. Usually events are received faster. The value must
711 * be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
712 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired delay
713 * between events in microseconds. Specifying the delay in microseconds only works
714 * from Android 2.3 (API level 9) onwards. For earlier releases, you must use one of
715 * the {@code SENSOR_DELAY_*} constants.
716 * @return <code>true</code> if the sensor is supported and successfully enabled.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700717 * @see #registerListener(SensorEventListener, Sensor, int, Handler)
718 * @see #unregisterListener(SensorEventListener)
719 * @see #unregisterListener(SensorEventListener, Sensor)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 */
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700721 public boolean registerListener(SensorEventListener listener, Sensor sensor,
722 int samplingPeriodUs) {
723 return registerListener(listener, sensor, samplingPeriodUs, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800724 }
725
726 /**
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700727 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
728 * sensor at the given sampling frequency and the given maximum reporting latency.
Aravind Akellab4c76b12013-06-27 12:04:16 -0700729 * <p>
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700730 * This function is similar to {@link #registerListener(SensorEventListener, Sensor, int)} but
731 * it allows events to stay temporarily in the hardware FIFO (queue) before being delivered. The
732 * events can be stored in the hardware FIFO up to {@code maxReportLatencyUs} microseconds. Once
733 * one of the events in the FIFO needs to be reported, all of the events in the FIFO are
734 * reported sequentially. This means that some events will be reported before the maximum
735 * reporting latency has elapsed.
736 * </p><p>
737 * When {@code maxReportLatencyUs} is 0, the call is equivalent to a call to
738 * {@link #registerListener(SensorEventListener, Sensor, int)}, as it requires the events to be
739 * delivered as soon as possible.
740 * </p><p>
741 * When {@code sensor.maxFifoEventCount()} is 0, the sensor does not use a FIFO, so the call
742 * will also be equivalent to {@link #registerListener(SensorEventListener, Sensor, int)}.
743 * </p><p>
744 * Setting {@code maxReportLatencyUs} to a positive value allows to reduce the number of
745 * interrupts the AP (Application Processor) receives, hence reducing power consumption, as the
746 * AP can switch to a lower power state while the sensor is capturing the data. This is
747 * especially important when registering to wake-up sensors, for which each interrupt causes the
748 * AP to wake up if it was in suspend mode. See {@link Sensor#isWakeUpSensor()} for more
749 * information on wake-up sensors.
Aravind Akellab4c76b12013-06-27 12:04:16 -0700750 * </p>
751 * <p class="note">
752 * </p>
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700753 * Note: Don't use this method with one-shot trigger sensors such as
Aravind Akellab4c76b12013-06-27 12:04:16 -0700754 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use
755 * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p>
756 *
757 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700758 * that will receive the sensor events. If the application is interested in receiving
759 * flush complete notifications, it should register with
760 * {@link android.hardware.SensorEventListener SensorEventListener2} instead.
Aravind Akellab4c76b12013-06-27 12:04:16 -0700761 * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700762 * @param samplingPeriodUs The desired delay between two consecutive events in microseconds.
763 * This is only a hint to the system. Events may be received faster or slower than
764 * the specified rate. Usually events are received faster. Can be one of
Aravind Akellab4c76b12013-06-27 12:04:16 -0700765 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
766 * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in
767 * microseconds.
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700768 * @param maxReportLatencyUs Maximum time in microseconds that events can be delayed before
769 * being reported to the application. A large value allows reducing the power
770 * consumption associated with the sensor. If maxReportLatencyUs is set to zero,
771 * events are delivered as soon as they are available, which is equivalent to calling
Aravind Akellab4c76b12013-06-27 12:04:16 -0700772 * {@link #registerListener(SensorEventListener, Sensor, int)}.
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700773 * @return <code>true</code> if the sensor is supported and successfully enabled.
Aravind Akellab4c76b12013-06-27 12:04:16 -0700774 * @see #registerListener(SensorEventListener, Sensor, int)
775 * @see #unregisterListener(SensorEventListener)
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700776 * @see #flush(SensorEventListener)
Aravind Akellab4c76b12013-06-27 12:04:16 -0700777 */
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700778 public boolean registerListener(SensorEventListener listener, Sensor sensor,
779 int samplingPeriodUs, int maxReportLatencyUs) {
780 int delay = getDelay(samplingPeriodUs);
781 return registerListenerImpl(listener, sensor, delay, null, maxReportLatencyUs, 0);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700782 }
783
784 /**
785 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
Aravind Akellad405e0f2013-09-04 12:07:33 -0700786 * sensor. Events are delivered in continuous mode as soon as they are available. To reduce the
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700787 * power consumption, applications can use
788 * {@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a
789 * positive non-zero maximum reporting latency.
790 * <p class="note">
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800791 * </p>
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700792 * Note: Don't use this method with a one shot trigger sensor such as
793 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use
794 * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p>
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800795 *
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700796 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object.
797 * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
798 * @param samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are
799 * delivered at. This is only a hint to the system. Events may be received faster or
800 * slower than the specified rate. Usually events are received faster. The value must
801 * be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
802 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired
803 * delay between events in microseconds. Specifying the delay in microseconds only
804 * works from Android 2.3 (API level 9) onwards. For earlier releases, you must use
805 * one of the {@code SENSOR_DELAY_*} constants.
806 * @param handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent
807 * sensor events} will be delivered to.
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700808 * @return <code>true</code> if the sensor is supported and successfully enabled.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700809 * @see #registerListener(SensorEventListener, Sensor, int)
810 * @see #unregisterListener(SensorEventListener)
811 * @see #unregisterListener(SensorEventListener, Sensor)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 */
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700813 public boolean registerListener(SensorEventListener listener, Sensor sensor,
814 int samplingPeriodUs, Handler handler) {
815 int delay = getDelay(samplingPeriodUs);
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700816 return registerListenerImpl(listener, sensor, delay, handler, 0, 0);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800818
Aravind Akellab4c76b12013-06-27 12:04:16 -0700819 /**
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700820 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
821 * sensor at the given sampling frequency and the given maximum reporting latency.
822 *
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700823 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
824 * that will receive the sensor events. If the application is interested in receiving
825 * flush complete notifications, it should register with
826 * {@link android.hardware.SensorEventListener SensorEventListener2} instead.
827 * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700828 * @param samplingPeriodUs The desired delay between two consecutive events in microseconds.
829 * This is only a hint to the system. Events may be received faster or slower than
830 * the specified rate. Usually events are received faster. Can be one of
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700831 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
832 * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in
833 * microseconds.
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700834 * @param maxReportLatencyUs Maximum time in microseconds that events can be delayed before
835 * being reported to the application. A large value allows reducing the power
836 * consumption associated with the sensor. If maxReportLatencyUs is set to zero,
837 * events are delivered as soon as they are available, which is equivalent to calling
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700838 * {@link #registerListener(SensorEventListener, Sensor, int)}.
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700839 * @param handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent
840 * sensor events} will be delivered to.
841 * @return <code>true</code> if the sensor is supported and successfully enabled.
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700842 * @see #registerListener(SensorEventListener, Sensor, int, int)
Aravind Akellab4c76b12013-06-27 12:04:16 -0700843 */
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700844 public boolean registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs,
845 int maxReportLatencyUs, Handler handler) {
846 int delayUs = getDelay(samplingPeriodUs);
847 return registerListenerImpl(listener, sensor, delayUs, handler, maxReportLatencyUs, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 }
849
Jeff Brown25157e42012-04-16 12:13:05 -0700850 /** @hide */
851 protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700852 int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700853
854
855 /**
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700856 * Flushes the FIFO of all the sensors registered for this listener. If there are events
857 * in the FIFO of the sensor, they are returned as if the maxReportLantecy of the FIFO has
858 * expired. Events are returned in the usual way through the SensorEventListener.
859 * This call doesn't affect the maxReportLantecy for this sensor. This call is asynchronous and
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700860 * returns immediately.
861 * {@link android.hardware.SensorEventListener2#onFlushCompleted onFlushCompleted} is called
862 * after all the events in the batch at the time of calling this method have been delivered
863 * successfully. If the hardware doesn't support flush, it still returns true and a trivial
864 * flush complete event is sent after the current event for all the clients registered for this
865 * sensor.
866 *
867 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
868 * which was previously used in a registerListener call.
869 * @return <code>true</code> if the flush is initiated successfully on all the sensors
870 * registered for this listener, false if no sensor is previously registered for this
871 * listener or flush on one of the sensors fails.
872 * @see #registerListener(SensorEventListener, Sensor, int, int)
873 * @throws IllegalArgumentException when listener is null.
Aravind Akellab4c76b12013-06-27 12:04:16 -0700874 */
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700875 public boolean flush(SensorEventListener listener) {
876 return flushImpl(listener);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700877 }
878
879 /** @hide */
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700880 protected abstract boolean flushImpl(SensorEventListener listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881
Peng Xua35b5532016-01-20 00:05:45 -0800882
883 /**
884 * Used for receiving notifications from the SensorManager when dynamic sensors are connected or
885 * disconnected.
886 */
887 public static abstract class DynamicSensorConnectionCallback {
888 /**
889 * Called when there is a dynamic sensor being connected to the system.
890 *
891 * @param sensor the newly connected sensor. See {@link android.hardware.Sensor Sensor}.
892 */
893 public void onDynamicSensorConnected(Sensor sensor) {}
894
895 /**
896 * Called when there is a dynamic sensor being disconnected from the system.
897 *
898 * @param sensor the disconnected sensor. See {@link android.hardware.Sensor Sensor}.
899 */
900 public void onDynamicSensorDisconnected(Sensor sensor) {}
901 }
902
903
904 /**
905 * Add a {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
906 * DynamicSensorConnectionCallback} to receive dynamic sensor connection callbacks. Repeat
907 * registration with the already registered callback object will have no additional effect.
908 *
909 * @param callback An object that implements the
910 * {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
911 * DynamicSensorConnectionCallback}
912 * interface for receiving callbacks.
913 * @see #addDynamicSensorCallback(DynamicSensorConnectionCallback, Handler)
914 *
915 * @throws IllegalArgumentException when callback is null.
916 */
917 public void registerDynamicSensorCallback(DynamicSensorConnectionCallback callback) {
918 registerDynamicSensorCallback(callback, null);
919 }
920
921 /**
922 * Add a {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
923 * DynamicSensorConnectionCallback} to receive dynamic sensor connection callbacks. Repeat
924 * registration with the already registered callback object will have no additional effect.
925 *
926 * @param callback An object that implements the
927 * {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
928 * DynamicSensorConnectionCallback} interface for receiving callbacks.
929 * @param handler The {@link android.os.Handler Handler} the {@link
930 * android.hardware.SensorManager.DynamicSensorConnectionCallback
931 * sensor connection events} will be delivered to.
932 *
933 * @throws IllegalArgumentException when callback is null.
934 */
935 public void registerDynamicSensorCallback(
936 DynamicSensorConnectionCallback callback, Handler handler) {
937 registerDynamicSensorCallbackImpl(callback, handler);
938 }
939
940 /**
941 * Remove a {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
942 * DynamicSensorConnectionCallback} to stop sending dynamic sensor connection events to that
943 * callback.
944 *
945 * @param callback An object that implements the
946 * {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
947 * DynamicSensorConnectionCallback}
948 * interface for receiving callbacks.
949 */
950 public void unregisterDynamicSensorCallback(DynamicSensorConnectionCallback callback) {
951 unregisterDynamicSensorCallbackImpl(callback);
952 }
953
954 /** @hide */
955 protected abstract void registerDynamicSensorCallbackImpl(
956 DynamicSensorConnectionCallback callback, Handler handler);
957
958 /** @hide */
959 protected abstract void unregisterDynamicSensorCallbackImpl(
960 DynamicSensorConnectionCallback callback);
961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700963 * <p>
964 * Computes the inclination matrix <b>I</b> as well as the rotation matrix
965 * <b>R</b> transforming a vector from the device coordinate system to the
966 * world's coordinate system which is defined as a direct orthonormal basis,
967 * where:
968 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -0700969 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700970 * <ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971 * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
972 * the ground at the device's current location and roughly points East).</li>
973 * <li>Y is tangential to the ground at the device's current location and
974 * points towards the magnetic North Pole.</li>
975 * <li>Z points towards the sky and is perpendicular to the ground.</li>
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700976 * </ul>
Mathias Agopian0f791a72010-06-22 21:55:01 -0700977 *
978 * <p>
979 * <center><img src="../../../images/axis_globe.png"
Mathias Agopianf71384c2010-11-19 16:25:11 -0800980 * alt="World coordinate-system diagram." border="0" /></center>
Mathias Agopian0f791a72010-06-22 21:55:01 -0700981 * </p>
982 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 * <p>
984 * <hr>
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700985 * <p>
986 * By definition:
987 * <p>
988 * [0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity)
989 * <p>
990 * [0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b> (m = magnitude of
991 * geomagnetic field)
992 * <p>
993 * <b>R</b> is the identity matrix when the device is aligned with the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 * world's coordinate system, that is, when the device's X axis points
995 * toward East, the Y axis points to the North Pole and the device is facing
996 * the sky.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700997 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700998 * <p>
999 * <b>I</b> is a rotation matrix transforming the geomagnetic vector into
1000 * the same coordinate space as gravity (the world's coordinate space).
1001 * <b>I</b> is a simple rotation around the X axis. The inclination angle in
1002 * radians can be computed with {@link #getInclination}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 * <hr>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001004 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001005 * <p>
1006 * Each matrix is returned either as a 3x3 or 4x4 row-major matrix depending
1007 * on the length of the passed array:
1008 * <p>
1009 * <u>If the array length is 16:</u>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001010 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 * <pre>
1012 * / M[ 0] M[ 1] M[ 2] M[ 3] \
1013 * | M[ 4] M[ 5] M[ 6] M[ 7] |
1014 * | M[ 8] M[ 9] M[10] M[11] |
1015 * \ M[12] M[13] M[14] M[15] /
1016 *</pre>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001017 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001018 * This matrix is ready to be used by OpenGL ES's
1019 * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int)
1020 * glLoadMatrixf(float[], int)}.
1021 * <p>
1022 * Note that because OpenGL matrices are column-major matrices you must
1023 * transpose the matrix before using it. However, since the matrix is a
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 * rotation matrix, its transpose is also its inverse, conveniently, it is
1025 * often the inverse of the rotation that is needed for rendering; it can
1026 * therefore be used with OpenGL ES directly.
1027 * <p>
1028 * Also note that the returned matrices always have this form:
Mathias Agopian0f791a72010-06-22 21:55:01 -07001029 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 * <pre>
1031 * / M[ 0] M[ 1] M[ 2] 0 \
1032 * | M[ 4] M[ 5] M[ 6] 0 |
1033 * | M[ 8] M[ 9] M[10] 0 |
1034 * \ 0 0 0 1 /
1035 *</pre>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001036 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001037 * <p>
1038 * <u>If the array length is 9:</u>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001039 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 * <pre>
1041 * / M[ 0] M[ 1] M[ 2] \
1042 * | M[ 3] M[ 4] M[ 5] |
1043 * \ M[ 6] M[ 7] M[ 8] /
1044 *</pre>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001045 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001046 * <hr>
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001047 * <p>
1048 * The inverse of each matrix can be computed easily by taking its
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 * transpose.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001050 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001051 * <p>
1052 * The matrices returned by this function are meaningful only when the
1053 * device is not free-falling and it is not close to the magnetic north. If
1054 * the device is accelerating, or placed into a strong magnetic field, the
1055 * returned matrices may be inaccurate.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001056 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001057 * @param R
1058 * is an array of 9 floats holding the rotation matrix <b>R</b> when
1059 * this function returns. R can be null.
1060 * <p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001061 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001062 * @param I
1063 * is an array of 9 floats holding the rotation matrix <b>I</b> when
1064 * this function returns. I can be null.
1065 * <p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001066 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001067 * @param gravity
1068 * is an array of 3 floats containing the gravity vector expressed in
1069 * the device's coordinate. You can simply use the
1070 * {@link android.hardware.SensorEvent#values values} returned by a
1071 * {@link android.hardware.SensorEvent SensorEvent} of a
1072 * {@link android.hardware.Sensor Sensor} of type
1073 * {@link android.hardware.Sensor#TYPE_ACCELEROMETER
1074 * TYPE_ACCELEROMETER}.
1075 * <p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001076 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001077 * @param geomagnetic
1078 * is an array of 3 floats containing the geomagnetic vector
1079 * expressed in the device's coordinate. You can simply use the
1080 * {@link android.hardware.SensorEvent#values values} returned by a
1081 * {@link android.hardware.SensorEvent SensorEvent} of a
1082 * {@link android.hardware.Sensor Sensor} of type
1083 * {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD
1084 * TYPE_MAGNETIC_FIELD}.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001085 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001086 * @return <code>true</code> on success, <code>false</code> on failure (for
Peng Xuca09d8c2015-05-21 18:06:06 -07001087 * instance, if the device is in free fall). Free fall is defined as
1088 * condition when the magnitude of the gravity is less than 1/10 of
1089 * the nominal value. On failure the output matrices are not modified.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001090 *
1091 * @see #getInclination(float[])
1092 * @see #getOrientation(float[], float[])
1093 * @see #remapCoordinateSystem(float[], int, int, float[])
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 */
1095
1096 public static boolean getRotationMatrix(float[] R, float[] I,
1097 float[] gravity, float[] geomagnetic) {
1098 // TODO: move this to native code for efficiency
1099 float Ax = gravity[0];
1100 float Ay = gravity[1];
1101 float Az = gravity[2];
Peng Xuca09d8c2015-05-21 18:06:06 -07001102
1103 final float normsqA = (Ax*Ax + Ay*Ay + Az*Az);
1104 final float g = 9.81f;
1105 final float freeFallGravitySquared = 0.01f * g * g;
1106 if (normsqA < freeFallGravitySquared) {
1107 // gravity less than 10% of normal value
1108 return false;
1109 }
1110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 final float Ex = geomagnetic[0];
1112 final float Ey = geomagnetic[1];
1113 final float Ez = geomagnetic[2];
1114 float Hx = Ey*Az - Ez*Ay;
1115 float Hy = Ez*Ax - Ex*Az;
1116 float Hz = Ex*Ay - Ey*Ax;
1117 final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
Peng Xuca09d8c2015-05-21 18:06:06 -07001118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 if (normH < 0.1f) {
1120 // device is close to free fall (or in space?), or close to
1121 // magnetic north pole. Typical values are > 100.
1122 return false;
1123 }
1124 final float invH = 1.0f / normH;
1125 Hx *= invH;
1126 Hy *= invH;
1127 Hz *= invH;
1128 final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
1129 Ax *= invA;
1130 Ay *= invA;
1131 Az *= invA;
1132 final float Mx = Ay*Hz - Az*Hy;
1133 final float My = Az*Hx - Ax*Hz;
1134 final float Mz = Ax*Hy - Ay*Hx;
1135 if (R != null) {
1136 if (R.length == 9) {
1137 R[0] = Hx; R[1] = Hy; R[2] = Hz;
1138 R[3] = Mx; R[4] = My; R[5] = Mz;
1139 R[6] = Ax; R[7] = Ay; R[8] = Az;
1140 } else if (R.length == 16) {
1141 R[0] = Hx; R[1] = Hy; R[2] = Hz; R[3] = 0;
1142 R[4] = Mx; R[5] = My; R[6] = Mz; R[7] = 0;
1143 R[8] = Ax; R[9] = Ay; R[10] = Az; R[11] = 0;
1144 R[12] = 0; R[13] = 0; R[14] = 0; R[15] = 1;
1145 }
1146 }
1147 if (I != null) {
1148 // compute the inclination matrix by projecting the geomagnetic
1149 // vector onto the Z (gravity) and X (horizontal component
1150 // of geomagnetic vector) axes.
1151 final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
1152 final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
1153 final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
1154 if (I.length == 9) {
1155 I[0] = 1; I[1] = 0; I[2] = 0;
1156 I[3] = 0; I[4] = c; I[5] = s;
1157 I[6] = 0; I[7] =-s; I[8] = c;
1158 } else if (I.length == 16) {
1159 I[0] = 1; I[1] = 0; I[2] = 0;
1160 I[4] = 0; I[5] = c; I[6] = s;
1161 I[8] = 0; I[9] =-s; I[10]= c;
1162 I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
1163 I[15] = 1;
1164 }
1165 }
1166 return true;
1167 }
1168
1169 /**
1170 * Computes the geomagnetic inclination angle in radians from the
1171 * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001172 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001173 * @param I
1174 * inclination matrix see {@link #getRotationMatrix}.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001175 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001176 * @return The geomagnetic inclination angle in radians.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001177 *
1178 * @see #getRotationMatrix(float[], float[], float[], float[])
1179 * @see #getOrientation(float[], float[])
1180 * @see GeomagneticField
1181 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 */
1183 public static float getInclination(float[] I) {
1184 if (I.length == 9) {
1185 return (float)Math.atan2(I[5], I[4]);
1186 } else {
Mathias Agopian0f791a72010-06-22 21:55:01 -07001187 return (float)Math.atan2(I[6], I[5]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001188 }
1189 }
1190
1191 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001192 * <p>
1193 * Rotates the supplied rotation matrix so it is expressed in a different
1194 * coordinate system. This is typically used when an application needs to
1195 * compute the three orientation angles of the device (see
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196 * {@link #getOrientation}) in a different coordinate system.
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001197 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001198 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001199 * <p>
1200 * When the rotation matrix is used for drawing (for instance with OpenGL
1201 * ES), it usually <b>doesn't need</b> to be transformed by this function,
1202 * unless the screen is physically rotated, in which case you can use
1203 * {@link android.view.Display#getRotation() Display.getRotation()} to
1204 * retrieve the current rotation of the screen. Note that because the user
1205 * is generally free to rotate their screen, you often should consider the
1206 * rotation in deciding the parameters to use here.
1207 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001208 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001209 * <p>
1210 * <u>Examples:</u>
1211 * <p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001212 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001213 * <ul>
1214 * <li>Using the camera (Y axis along the camera's axis) for an augmented
1215 * reality application where the rotation angles are needed:</li>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001216 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001217 * <p>
1218 * <ul>
1219 * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code>
1220 * </ul>
1221 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001222 *
Dianne Hackborn5cb70b52010-02-25 17:01:14 -08001223 * <li>Using the device as a mechanical compass when rotation is
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001224 * {@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:</li>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001225 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001226 * <p>
1227 * <ul>
1228 * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code>
1229 * </ul>
1230 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001231 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001232 * Beware of the above example. This call is needed only to account for a
1233 * rotation from its natural orientation when calculating the rotation
1234 * angles (see {@link #getOrientation}). If the rotation matrix is also used
1235 * for rendering, it may not need to be transformed, for instance if your
1236 * {@link android.app.Activity Activity} is running in landscape mode.
1237 * </ul>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001238 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001239 * <p>
1240 * Since the resulting coordinate system is orthonormal, only two axes need
1241 * to be specified.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001242 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001243 * @param inR
1244 * the rotation matrix to be transformed. Usually it is the matrix
1245 * returned by {@link #getRotationMatrix}.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001246 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001247 * @param X
Peng Xuca09d8c2015-05-21 18:06:06 -07001248 * defines the axis of the new cooridinate system that coincide with the X axis of the
1249 * original coordinate system.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001250 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001251 * @param Y
Peng Xuca09d8c2015-05-21 18:06:06 -07001252 * defines the axis of the new cooridinate system that coincide with the Y axis of the
1253 * original coordinate system.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001254 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001255 * @param outR
Katie McCormickf2ef28d2013-11-26 11:10:54 -08001256 * the transformed rotation matrix. inR and outR should not be the same
1257 * array.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001258 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001259 * @return <code>true</code> on success. <code>false</code> if the input
1260 * parameters are incorrect, for instance if X and Y define the same
1261 * axis. Or if inR and outR don't have the same length.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001262 *
1263 * @see #getRotationMatrix(float[], float[], float[], float[])
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264 */
1265
1266 public static boolean remapCoordinateSystem(float[] inR, int X, int Y,
1267 float[] outR)
1268 {
1269 if (inR == outR) {
1270 final float[] temp = mTempMatrix;
1271 synchronized(temp) {
1272 // we don't expect to have a lot of contention
1273 if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
1274 final int size = outR.length;
1275 for (int i=0 ; i<size ; i++)
1276 outR[i] = temp[i];
1277 return true;
1278 }
1279 }
1280 }
1281 return remapCoordinateSystemImpl(inR, X, Y, outR);
1282 }
1283
1284 private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y,
1285 float[] outR)
1286 {
1287 /*
1288 * X and Y define a rotation matrix 'r':
1289 *
1290 * (X==1)?((X&0x80)?-1:1):0 (X==2)?((X&0x80)?-1:1):0 (X==3)?((X&0x80)?-1:1):0
1291 * (Y==1)?((Y&0x80)?-1:1):0 (Y==2)?((Y&0x80)?-1:1):0 (Y==3)?((X&0x80)?-1:1):0
1292 * r[0] ^ r[1]
1293 *
1294 * where the 3rd line is the vector product of the first 2 lines
1295 *
1296 */
1297
1298 final int length = outR.length;
1299 if (inR.length != length)
1300 return false; // invalid parameter
1301 if ((X & 0x7C)!=0 || (Y & 0x7C)!=0)
1302 return false; // invalid parameter
1303 if (((X & 0x3)==0) || ((Y & 0x3)==0))
1304 return false; // no axis specified
1305 if ((X & 0x3) == (Y & 0x3))
1306 return false; // same axis specified
1307
1308 // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
1309 // this can be calculated by exclusive-or'ing X and Y; except for
1310 // the sign inversion (+/-) which is calculated below.
1311 int Z = X ^ Y;
1312
1313 // extract the axis (remove the sign), offset in the range 0 to 2.
1314 final int x = (X & 0x3)-1;
1315 final int y = (Y & 0x3)-1;
1316 final int z = (Z & 0x3)-1;
1317
1318 // compute the sign of Z (whether it needs to be inverted)
1319 final int axis_y = (z+1)%3;
1320 final int axis_z = (z+2)%3;
1321 if (((x^axis_y)|(y^axis_z)) != 0)
1322 Z ^= 0x80;
1323
1324 final boolean sx = (X>=0x80);
1325 final boolean sy = (Y>=0x80);
1326 final boolean sz = (Z>=0x80);
1327
1328 // Perform R * r, in avoiding actual muls and adds.
1329 final int rowLength = ((length==16)?4:3);
1330 for (int j=0 ; j<3 ; j++) {
1331 final int offset = j*rowLength;
1332 for (int i=0 ; i<3 ; i++) {
1333 if (x==i) outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0];
1334 if (y==i) outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1];
1335 if (z==i) outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2];
1336 }
1337 }
1338 if (length == 16) {
1339 outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
1340 outR[15] = 1;
1341 }
1342 return true;
1343 }
1344
1345 /**
1346 * Computes the device's orientation based on the rotation matrix.
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001347 * <p>
1348 * When it returns, the array values is filled with the result:
1349 * <ul>
Peng Xuca09d8c2015-05-21 18:06:06 -07001350 * <li>values[0]: <i>azimuth</i>, rotation around the -Z axis,
1351 * i.e. the opposite direction of Z axis.</li>
1352 * <li>values[1]: <i>pitch</i>, rotation around the -X axis,
1353 * i.e the opposite direction of X axis.</li>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001354 * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li>
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001355 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356 * <p>
Peng Xuca09d8c2015-05-21 18:06:06 -07001357 * Applying these three intrinsic rotations in azimuth, pitch and roll order transforms
1358 * identity matrix to the rotation matrix given in input R.
Mathias Agopian210fc912010-02-26 13:51:39 -08001359 * All three angles above are in <b>radians</b> and <b>positive</b> in the
Peng Xuca09d8c2015-05-21 18:06:06 -07001360 * <b>counter-clockwise</b> direction. Range of output is: azimuth from -&pi; to &pi;,
1361 * pitch from -&pi;/2 to &pi;/2 and roll from -&pi; to &pi;.
Aravind Akellab4c76b12013-06-27 12:04:16 -07001362 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001363 * @param R
1364 * rotation matrix see {@link #getRotationMatrix}.
Aravind Akellab4c76b12013-06-27 12:04:16 -07001365 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001366 * @param values
1367 * an array of 3 floats to hold the result.
Aravind Akellab4c76b12013-06-27 12:04:16 -07001368 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 * @return The array values passed as argument.
Aravind Akellab4c76b12013-06-27 12:04:16 -07001370 *
Mathias Agopian0f791a72010-06-22 21:55:01 -07001371 * @see #getRotationMatrix(float[], float[], float[], float[])
1372 * @see GeomagneticField
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 */
Mathias Agopian04d7e83e2010-07-29 17:59:58 -07001374 public static float[] getOrientation(float[] R, float values[]) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 /*
1376 * 4x4 (length=16) case:
1377 * / R[ 0] R[ 1] R[ 2] 0 \
1378 * | R[ 4] R[ 5] R[ 6] 0 |
1379 * | R[ 8] R[ 9] R[10] 0 |
1380 * \ 0 0 0 1 /
Mathias Agopian0f791a72010-06-22 21:55:01 -07001381 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 * 3x3 (length=9) case:
1383 * / R[ 0] R[ 1] R[ 2] \
1384 * | R[ 3] R[ 4] R[ 5] |
1385 * \ R[ 6] R[ 7] R[ 8] /
Mathias Agopian0f791a72010-06-22 21:55:01 -07001386 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001387 */
1388 if (R.length == 9) {
1389 values[0] = (float)Math.atan2(R[1], R[4]);
1390 values[1] = (float)Math.asin(-R[7]);
1391 values[2] = (float)Math.atan2(-R[6], R[8]);
1392 } else {
1393 values[0] = (float)Math.atan2(R[1], R[5]);
1394 values[1] = (float)Math.asin(-R[9]);
1395 values[2] = (float)Math.atan2(-R[8], R[10]);
1396 }
Peng Xuca09d8c2015-05-21 18:06:06 -07001397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398 return values;
1399 }
1400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401 /**
Mathias Agopian04d7e83e2010-07-29 17:59:58 -07001402 * Computes the Altitude in meters from the atmospheric pressure and the
1403 * pressure at sea level.
1404 * <p>
1405 * Typically the atmospheric pressure is read from a
1406 * {@link Sensor#TYPE_PRESSURE} sensor. The pressure at sea level must be
1407 * known, usually it can be retrieved from airport databases in the
Mathias Agopiana6704d32010-08-18 12:00:30 -07001408 * vicinity. If unknown, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE}
1409 * as an approximation, but absolute altitudes won't be accurate.
1410 * </p>
1411 * <p>
1412 * To calculate altitude differences, you must calculate the difference
1413 * between the altitudes at both points. If you don't know the altitude
1414 * as sea level, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE} instead,
1415 * which will give good results considering the range of pressure typically
1416 * involved.
1417 * </p>
1418 * <p>
1419 * <code><ul>
1420 * float altitude_difference =
1421 * getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point2)
1422 * - getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point1);
1423 * </ul></code>
Mathias Agopian04d7e83e2010-07-29 17:59:58 -07001424 * </p>
1425 *
1426 * @param p0 pressure at sea level
1427 * @param p atmospheric pressure
1428 * @return Altitude in meters
1429 */
Jeff Brown25157e42012-04-16 12:13:05 -07001430 public static float getAltitude(float p0, float p) {
Mathias Agopian04d7e83e2010-07-29 17:59:58 -07001431 final float coef = 1.0f / 5.255f;
1432 return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef));
1433 }
1434
Kevin Powell7a0541d2010-07-19 19:10:40 -07001435 /** Helper function to compute the angle change between two rotation matrices.
1436 * Given a current rotation matrix (R) and a previous rotation matrix
Peng Xuca09d8c2015-05-21 18:06:06 -07001437 * (prevR) computes the intrinsic rotation around the z, x, and y axes which
Kevin Powell7a0541d2010-07-19 19:10:40 -07001438 * transforms prevR to R.
Peng Xuca09d8c2015-05-21 18:06:06 -07001439 * outputs a 3 element vector containing the z, x, and y angle
Kevin Powell7a0541d2010-07-19 19:10:40 -07001440 * change at indexes 0, 1, and 2 respectively.
1441 * <p> Each input matrix is either as a 3x3 or 4x4 row-major matrix
1442 * depending on the length of the passed array:
1443 * <p>If the array length is 9, then the array elements represent this matrix
1444 * <pre>
1445 * / R[ 0] R[ 1] R[ 2] \
1446 * | R[ 3] R[ 4] R[ 5] |
1447 * \ R[ 6] R[ 7] R[ 8] /
1448 *</pre>
1449 * <p>If the array length is 16, then the array elements represent this matrix
1450 * <pre>
1451 * / R[ 0] R[ 1] R[ 2] R[ 3] \
1452 * | R[ 4] R[ 5] R[ 6] R[ 7] |
1453 * | R[ 8] R[ 9] R[10] R[11] |
1454 * \ R[12] R[13] R[14] R[15] /
1455 *</pre>
Peng Xuca09d8c2015-05-21 18:06:06 -07001456 *
1457 * See {@link #getOrientation} for more detailed definition of the output.
1458 *
Kevin Powell7a0541d2010-07-19 19:10:40 -07001459 * @param R current rotation matrix
1460 * @param prevR previous rotation matrix
Peng Xuca09d8c2015-05-21 18:06:06 -07001461 * @param angleChange an an array of floats (z, x, and y) in which the angle change
1462 * (in radians) is stored
Kevin Powell7a0541d2010-07-19 19:10:40 -07001463 */
1464
1465 public static void getAngleChange( float[] angleChange, float[] R, float[] prevR) {
1466 float rd1=0,rd4=0, rd6=0,rd7=0, rd8=0;
1467 float ri0=0,ri1=0,ri2=0,ri3=0,ri4=0,ri5=0,ri6=0,ri7=0,ri8=0;
1468 float pri0=0, pri1=0, pri2=0, pri3=0, pri4=0, pri5=0, pri6=0, pri7=0, pri8=0;
Kevin Powell7a0541d2010-07-19 19:10:40 -07001469
1470 if(R.length == 9) {
1471 ri0 = R[0];
1472 ri1 = R[1];
1473 ri2 = R[2];
1474 ri3 = R[3];
1475 ri4 = R[4];
1476 ri5 = R[5];
1477 ri6 = R[6];
1478 ri7 = R[7];
1479 ri8 = R[8];
1480 } else if(R.length == 16) {
1481 ri0 = R[0];
1482 ri1 = R[1];
1483 ri2 = R[2];
1484 ri3 = R[4];
1485 ri4 = R[5];
1486 ri5 = R[6];
1487 ri6 = R[8];
1488 ri7 = R[9];
1489 ri8 = R[10];
1490 }
1491
1492 if(prevR.length == 9) {
Kevin Powell34884b42010-11-03 16:04:30 -07001493 pri0 = prevR[0];
1494 pri1 = prevR[1];
1495 pri2 = prevR[2];
1496 pri3 = prevR[3];
1497 pri4 = prevR[4];
1498 pri5 = prevR[5];
1499 pri6 = prevR[6];
1500 pri7 = prevR[7];
1501 pri8 = prevR[8];
Kevin Powell7a0541d2010-07-19 19:10:40 -07001502 } else if(prevR.length == 16) {
Kevin Powell34884b42010-11-03 16:04:30 -07001503 pri0 = prevR[0];
1504 pri1 = prevR[1];
1505 pri2 = prevR[2];
1506 pri3 = prevR[4];
1507 pri4 = prevR[5];
1508 pri5 = prevR[6];
1509 pri6 = prevR[8];
1510 pri7 = prevR[9];
1511 pri8 = prevR[10];
Kevin Powell7a0541d2010-07-19 19:10:40 -07001512 }
1513
1514 // calculate the parts of the rotation difference matrix we need
1515 // rd[i][j] = pri[0][i] * ri[0][j] + pri[1][i] * ri[1][j] + pri[2][i] * ri[2][j];
1516
1517 rd1 = pri0 * ri1 + pri3 * ri4 + pri6 * ri7; //rd[0][1]
1518 rd4 = pri1 * ri1 + pri4 * ri4 + pri7 * ri7; //rd[1][1]
1519 rd6 = pri2 * ri0 + pri5 * ri3 + pri8 * ri6; //rd[2][0]
1520 rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1]
1521 rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2]
1522
1523 angleChange[0] = (float)Math.atan2(rd1, rd4);
1524 angleChange[1] = (float)Math.asin(-rd7);
1525 angleChange[2] = (float)Math.atan2(-rd6, rd8);
1526
1527 }
1528
1529 /** Helper function to convert a rotation vector to a rotation matrix.
1530 * Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a
1531 * 9 or 16 element rotation matrix in the array R. R must have length 9 or 16.
1532 * If R.length == 9, the following matrix is returned:
1533 * <pre>
1534 * / R[ 0] R[ 1] R[ 2] \
1535 * | R[ 3] R[ 4] R[ 5] |
1536 * \ R[ 6] R[ 7] R[ 8] /
1537 *</pre>
1538 * If R.length == 16, the following matrix is returned:
1539 * <pre>
1540 * / R[ 0] R[ 1] R[ 2] 0 \
1541 * | R[ 4] R[ 5] R[ 6] 0 |
1542 * | R[ 8] R[ 9] R[10] 0 |
1543 * \ 0 0 0 1 /
1544 *</pre>
1545 * @param rotationVector the rotation vector to convert
1546 * @param R an array of floats in which to store the rotation matrix
1547 */
1548 public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) {
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001549
1550 float q0;
Kevin Powell7a0541d2010-07-19 19:10:40 -07001551 float q1 = rotationVector[0];
1552 float q2 = rotationVector[1];
1553 float q3 = rotationVector[2];
1554
Balint Ureczky12d39b92013-12-05 00:03:45 +01001555 if (rotationVector.length >= 4) {
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001556 q0 = rotationVector[3];
1557 } else {
Mathias Agopian7b6e4bd62011-02-14 16:34:07 -08001558 q0 = 1 - q1*q1 - q2*q2 - q3*q3;
1559 q0 = (q0 > 0) ? (float)Math.sqrt(q0) : 0;
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001560 }
1561
Kevin Powell7a0541d2010-07-19 19:10:40 -07001562 float sq_q1 = 2 * q1 * q1;
1563 float sq_q2 = 2 * q2 * q2;
1564 float sq_q3 = 2 * q3 * q3;
1565 float q1_q2 = 2 * q1 * q2;
1566 float q3_q0 = 2 * q3 * q0;
1567 float q1_q3 = 2 * q1 * q3;
1568 float q2_q0 = 2 * q2 * q0;
1569 float q2_q3 = 2 * q2 * q3;
1570 float q1_q0 = 2 * q1 * q0;
1571
1572 if(R.length == 9) {
1573 R[0] = 1 - sq_q2 - sq_q3;
1574 R[1] = q1_q2 - q3_q0;
1575 R[2] = q1_q3 + q2_q0;
1576
1577 R[3] = q1_q2 + q3_q0;
1578 R[4] = 1 - sq_q1 - sq_q3;
1579 R[5] = q2_q3 - q1_q0;
1580
1581 R[6] = q1_q3 - q2_q0;
1582 R[7] = q2_q3 + q1_q0;
1583 R[8] = 1 - sq_q1 - sq_q2;
1584 } else if (R.length == 16) {
1585 R[0] = 1 - sq_q2 - sq_q3;
1586 R[1] = q1_q2 - q3_q0;
1587 R[2] = q1_q3 + q2_q0;
1588 R[3] = 0.0f;
1589
1590 R[4] = q1_q2 + q3_q0;
1591 R[5] = 1 - sq_q1 - sq_q3;
1592 R[6] = q2_q3 - q1_q0;
1593 R[7] = 0.0f;
1594
1595 R[8] = q1_q3 - q2_q0;
1596 R[9] = q2_q3 + q1_q0;
1597 R[10] = 1 - sq_q1 - sq_q2;
1598 R[11] = 0.0f;
1599
1600 R[12] = R[13] = R[14] = 0.0f;
1601 R[15] = 1.0f;
1602 }
1603 }
1604
1605 /** Helper function to convert a rotation vector to a normalized quaternion.
1606 * Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a normalized
1607 * quaternion in the array Q. The quaternion is stored as [w, x, y, z]
1608 * @param rv the rotation vector to convert
1609 * @param Q an array of floats in which to store the computed quaternion
1610 */
1611 public static void getQuaternionFromVector(float[] Q, float[] rv) {
Balint Ureczky12d39b92013-12-05 00:03:45 +01001612 if (rv.length >= 4) {
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001613 Q[0] = rv[3];
1614 } else {
Mathias Agopian0eab8212011-03-07 17:49:54 -08001615 Q[0] = 1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2];
1616 Q[0] = (Q[0] > 0) ? (float)Math.sqrt(Q[0]) : 0;
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001617 }
Kevin Powell7a0541d2010-07-19 19:10:40 -07001618 Q[1] = rv[0];
1619 Q[2] = rv[1];
1620 Q[3] = rv[2];
1621 }
1622
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -08001623 /**
1624 * Requests receiving trigger events for a trigger sensor.
1625 *
1626 * <p>
1627 * When the sensor detects a trigger event condition, such as significant motion in
1628 * the case of the {@link Sensor#TYPE_SIGNIFICANT_MOTION}, the provided trigger listener
1629 * will be invoked once and then its request to receive trigger events will be canceled.
1630 * To continue receiving trigger events, the application must request to receive trigger
1631 * events again.
1632 * </p>
1633 *
1634 * @param listener The listener on which the
1635 * {@link TriggerEventListener#onTrigger(TriggerEvent)} will be delivered.
1636 * @param sensor The sensor to be enabled.
1637 *
1638 * @return true if the sensor was successfully enabled.
1639 *
1640 * @throws IllegalArgumentException when sensor is null or not a trigger sensor.
1641 */
1642 public boolean requestTriggerSensor(TriggerEventListener listener, Sensor sensor) {
1643 return requestTriggerSensorImpl(listener, sensor);
1644 }
1645
1646 /**
1647 * @hide
1648 */
1649 protected abstract boolean requestTriggerSensorImpl(TriggerEventListener listener,
1650 Sensor sensor);
1651
1652 /**
1653 * Cancels receiving trigger events for a trigger sensor.
1654 *
1655 * <p>
1656 * Note that a Trigger sensor will be auto disabled if
1657 * {@link TriggerEventListener#onTrigger(TriggerEvent)} has triggered.
1658 * This method is provided in case the user wants to explicitly cancel the request
1659 * to receive trigger events.
1660 * </p>
1661 *
1662 * @param listener The listener on which the
1663 * {@link TriggerEventListener#onTrigger(TriggerEvent)}
1664 * is delivered.It should be the same as the one used
1665 * in {@link #requestTriggerSensor(TriggerEventListener, Sensor)}
1666 * @param sensor The sensor for which the trigger request should be canceled.
1667 * If null, it cancels receiving trigger for all sensors associated
1668 * with the listener.
1669 *
1670 * @return true if successfully canceled.
1671 *
1672 * @throws IllegalArgumentException when sensor is a trigger sensor.
1673 */
1674 public boolean cancelTriggerSensor(TriggerEventListener listener, Sensor sensor) {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -07001675 return cancelTriggerSensorImpl(listener, sensor, true);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -08001676 }
1677
1678 /**
1679 * @hide
1680 */
1681 protected abstract boolean cancelTriggerSensorImpl(TriggerEventListener listener,
Jaikumar Ganesh2e900892013-04-11 10:40:33 -07001682 Sensor sensor, boolean disable);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -08001683
1684
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001685 /**
1686 * For testing purposes only. Not for third party applications.
1687 *
Aravind Akellad123b512015-06-29 12:35:51 -07001688 * Initialize data injection mode and create a client for data injection. SensorService should
1689 * already be operating in DATA_INJECTION mode for this call succeed. To set SensorService into
1690 * DATA_INJECTION mode "adb shell dumpsys sensorservice data_injection" needs to be called
1691 * through adb. Typically this is done using a host side test. This mode is expected to be used
1692 * only for testing purposes. If the HAL is set to data injection mode, it will ignore the input
1693 * from physical sensors and read sensor data that is injected from the test application. This
1694 * mode is used for testing vendor implementations for various algorithms like Rotation Vector,
1695 * Significant Motion, Step Counter etc. Not all HALs support DATA_INJECTION. This method will
1696 * fail in those cases. Once this method succeeds, the test can call
1697 * {@link injectSensorData(Sensor, float[], int, long)} to inject sensor data into the HAL.
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001698 *
Aravind Akellad123b512015-06-29 12:35:51 -07001699 * @param enable True to initialize a client in DATA_INJECTION mode.
1700 * False to clean up the native resources.
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001701 *
1702 * @return true if the HAL supports data injection and false
1703 * otherwise.
1704 * @hide
1705 */
1706 @SystemApi
Aravind Akellad123b512015-06-29 12:35:51 -07001707 public boolean initDataInjection(boolean enable) {
1708 return initDataInjectionImpl(enable);
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001709 }
1710
1711 /**
1712 * @hide
1713 */
Aravind Akellad123b512015-06-29 12:35:51 -07001714 protected abstract boolean initDataInjectionImpl(boolean enable);
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001715
1716 /**
1717 * For testing purposes only. Not for third party applications.
1718 *
Aravind Akellad123b512015-06-29 12:35:51 -07001719 * This method is used to inject raw sensor data into the HAL. Call {@link
1720 * initDataInjection(boolean)} before this method to set the HAL in data injection mode. This
1721 * method should be called only if a previous call to initDataInjection has been successful and
1722 * the HAL and SensorService are already opreating in data injection mode.
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001723 *
1724 * @param sensor The sensor to inject.
1725 * @param values Sensor values to inject. The length of this
1726 * array must be exactly equal to the number of
1727 * values reported by the sensor type.
1728 * @param accuracy Accuracy of the sensor.
1729 * @param timestamp Sensor timestamp associated with the event.
1730 *
1731 * @return boolean True if the data injection succeeds, false
1732 * otherwise.
1733 * @throws IllegalArgumentException when the sensor is null,
1734 * data injection is not supported by the sensor, values
1735 * are null, incorrect number of values for the sensor,
1736 * sensor accuracy is incorrect or timestamps are
1737 * invalid.
1738 * @hide
1739 */
1740 @SystemApi
1741 public boolean injectSensorData(Sensor sensor, float[] values, int accuracy,
1742 long timestamp) {
1743 if (sensor == null) {
1744 throw new IllegalArgumentException("sensor cannot be null");
1745 }
1746 if (!sensor.isDataInjectionSupported()) {
1747 throw new IllegalArgumentException("sensor does not support data injection");
1748 }
1749 if (values == null) {
1750 throw new IllegalArgumentException("sensor data cannot be null");
1751 }
Dianne Hackborn0e3de6c2015-07-29 15:20:21 -07001752 int expectedNumValues = Sensor.getMaxLengthValuesArray(sensor, Build.VERSION_CODES.M);
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001753 if (values.length != expectedNumValues) {
1754 throw new IllegalArgumentException ("Wrong number of values for sensor " +
1755 sensor.getName() + " actual=" + values.length + " expected=" +
1756 expectedNumValues);
1757 }
1758 if (accuracy < SENSOR_STATUS_NO_CONTACT || accuracy > SENSOR_STATUS_ACCURACY_HIGH) {
1759 throw new IllegalArgumentException("Invalid sensor accuracy");
1760 }
1761 if (timestamp <= 0) {
1762 throw new IllegalArgumentException("Negative or zero sensor timestamp");
1763 }
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001764 return injectSensorDataImpl(sensor, values, accuracy, timestamp);
1765 }
1766
1767 /**
1768 * @hide
1769 */
1770 protected abstract boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
1771 long timestamp);
1772
Jeff Brown4481d9c2012-04-16 16:14:44 -07001773 private LegacySensorManager getLegacySensorManager() {
1774 synchronized (mSensorListByType) {
1775 if (mLegacySensorManager == null) {
1776 Log.i(TAG, "This application is using deprecated SensorManager API which will "
1777 + "be removed someday. Please consider switching to the new API.");
1778 mLegacySensorManager = new LegacySensorManager(this);
Jeff Brown25157e42012-04-16 12:13:05 -07001779 }
Jeff Brown4481d9c2012-04-16 16:14:44 -07001780 return mLegacySensorManager;
Jeff Brown25157e42012-04-16 12:13:05 -07001781 }
1782 }
Aravind Akellab4c76b12013-06-27 12:04:16 -07001783
1784 private static int getDelay(int rate) {
1785 int delay = -1;
1786 switch (rate) {
1787 case SENSOR_DELAY_FASTEST:
1788 delay = 0;
1789 break;
1790 case SENSOR_DELAY_GAME:
1791 delay = 20000;
1792 break;
1793 case SENSOR_DELAY_UI:
1794 delay = 66667;
1795 break;
1796 case SENSOR_DELAY_NORMAL:
1797 delay = 200000;
1798 break;
1799 default:
1800 delay = rate;
1801 break;
1802 }
1803 return delay;
1804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805}