blob: 04ee1e6d57d03a7cbb7a48fb80339e2f11c23b23 [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 */
Peng Xufb1c9412016-03-29 21:50:43 -0700887 public static abstract class DynamicSensorCallback {
Peng Xua35b5532016-01-20 00:05:45 -0800888 /**
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 /**
Peng Xufb1c9412016-03-29 21:50:43 -0700905 * Add a {@link android.hardware.SensorManager.DynamicSensorCallback
906 * DynamicSensorCallback} to receive dynamic sensor connection callbacks. Repeat
Peng Xua35b5532016-01-20 00:05:45 -0800907 * registration with the already registered callback object will have no additional effect.
908 *
909 * @param callback An object that implements the
Peng Xufb1c9412016-03-29 21:50:43 -0700910 * {@link android.hardware.SensorManager.DynamicSensorCallback
911 * DynamicSensorCallback}
Peng Xua35b5532016-01-20 00:05:45 -0800912 * interface for receiving callbacks.
Peng Xufb1c9412016-03-29 21:50:43 -0700913 * @see #addDynamicSensorCallback(DynamicSensorCallback, Handler)
Peng Xua35b5532016-01-20 00:05:45 -0800914 *
915 * @throws IllegalArgumentException when callback is null.
916 */
Peng Xufb1c9412016-03-29 21:50:43 -0700917 public void registerDynamicSensorCallback(DynamicSensorCallback callback) {
Peng Xua35b5532016-01-20 00:05:45 -0800918 registerDynamicSensorCallback(callback, null);
919 }
920
921 /**
Peng Xufb1c9412016-03-29 21:50:43 -0700922 * Add a {@link android.hardware.SensorManager.DynamicSensorCallback
923 * DynamicSensorCallback} to receive dynamic sensor connection callbacks. Repeat
Peng Xua35b5532016-01-20 00:05:45 -0800924 * registration with the already registered callback object will have no additional effect.
925 *
926 * @param callback An object that implements the
Peng Xufb1c9412016-03-29 21:50:43 -0700927 * {@link android.hardware.SensorManager.DynamicSensorCallback
928 * DynamicSensorCallback} interface for receiving callbacks.
Peng Xua35b5532016-01-20 00:05:45 -0800929 * @param handler The {@link android.os.Handler Handler} the {@link
Peng Xufb1c9412016-03-29 21:50:43 -0700930 * android.hardware.SensorManager.DynamicSensorCallback
Peng Xua35b5532016-01-20 00:05:45 -0800931 * sensor connection events} will be delivered to.
932 *
933 * @throws IllegalArgumentException when callback is null.
934 */
935 public void registerDynamicSensorCallback(
Peng Xufb1c9412016-03-29 21:50:43 -0700936 DynamicSensorCallback callback, Handler handler) {
Peng Xua35b5532016-01-20 00:05:45 -0800937 registerDynamicSensorCallbackImpl(callback, handler);
938 }
939
940 /**
Peng Xufb1c9412016-03-29 21:50:43 -0700941 * Remove a {@link android.hardware.SensorManager.DynamicSensorCallback
942 * DynamicSensorCallback} to stop sending dynamic sensor connection events to that
Peng Xua35b5532016-01-20 00:05:45 -0800943 * callback.
944 *
945 * @param callback An object that implements the
Peng Xufb1c9412016-03-29 21:50:43 -0700946 * {@link android.hardware.SensorManager.DynamicSensorCallback
947 * DynamicSensorCallback}
Peng Xua35b5532016-01-20 00:05:45 -0800948 * interface for receiving callbacks.
949 */
Peng Xufb1c9412016-03-29 21:50:43 -0700950 public void unregisterDynamicSensorCallback(DynamicSensorCallback callback) {
Peng Xua35b5532016-01-20 00:05:45 -0800951 unregisterDynamicSensorCallbackImpl(callback);
952 }
953
Peng Xufb1c9412016-03-29 21:50:43 -0700954 /**
955 * Tell if dynamic sensor discovery feature is supported by system.
956 *
957 * @return <code>true</code> if dynamic sensor discovery is supported, <code>false</code>
958 * otherwise.
959 */
960 public boolean isDynamicSensorDiscoverySupported() {
961 List<Sensor> sensors = getSensorList(Sensor.TYPE_DYNAMIC_SENSOR_META);
962 return sensors.size() > 0;
963 }
964
Peng Xua35b5532016-01-20 00:05:45 -0800965 /** @hide */
966 protected abstract void registerDynamicSensorCallbackImpl(
Peng Xufb1c9412016-03-29 21:50:43 -0700967 DynamicSensorCallback callback, Handler handler);
Peng Xua35b5532016-01-20 00:05:45 -0800968
969 /** @hide */
970 protected abstract void unregisterDynamicSensorCallbackImpl(
Peng Xufb1c9412016-03-29 21:50:43 -0700971 DynamicSensorCallback callback);
Peng Xua35b5532016-01-20 00:05:45 -0800972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700974 * <p>
975 * Computes the inclination matrix <b>I</b> as well as the rotation matrix
976 * <b>R</b> transforming a vector from the device coordinate system to the
977 * world's coordinate system which is defined as a direct orthonormal basis,
978 * where:
979 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -0700980 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700981 * <ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
983 * the ground at the device's current location and roughly points East).</li>
984 * <li>Y is tangential to the ground at the device's current location and
985 * points towards the magnetic North Pole.</li>
986 * <li>Z points towards the sky and is perpendicular to the ground.</li>
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700987 * </ul>
Mathias Agopian0f791a72010-06-22 21:55:01 -0700988 *
989 * <p>
990 * <center><img src="../../../images/axis_globe.png"
Mathias Agopianf71384c2010-11-19 16:25:11 -0800991 * alt="World coordinate-system diagram." border="0" /></center>
Mathias Agopian0f791a72010-06-22 21:55:01 -0700992 * </p>
993 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 * <p>
995 * <hr>
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700996 * <p>
997 * By definition:
998 * <p>
999 * [0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity)
1000 * <p>
1001 * [0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b> (m = magnitude of
1002 * geomagnetic field)
1003 * <p>
1004 * <b>R</b> is the identity matrix when the device is aligned with the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 * world's coordinate system, that is, when the device's X axis points
1006 * toward East, the Y axis points to the North Pole and the device is facing
1007 * the sky.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001008 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001009 * <p>
1010 * <b>I</b> is a rotation matrix transforming the geomagnetic vector into
1011 * the same coordinate space as gravity (the world's coordinate space).
1012 * <b>I</b> is a simple rotation around the X axis. The inclination angle in
1013 * radians can be computed with {@link #getInclination}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 * <hr>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001015 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001016 * <p>
1017 * Each matrix is returned either as a 3x3 or 4x4 row-major matrix depending
1018 * on the length of the passed array:
1019 * <p>
1020 * <u>If the array length is 16:</u>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001021 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 * <pre>
1023 * / M[ 0] M[ 1] M[ 2] M[ 3] \
1024 * | M[ 4] M[ 5] M[ 6] M[ 7] |
1025 * | M[ 8] M[ 9] M[10] M[11] |
1026 * \ M[12] M[13] M[14] M[15] /
1027 *</pre>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001028 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001029 * This matrix is ready to be used by OpenGL ES's
1030 * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int)
1031 * glLoadMatrixf(float[], int)}.
1032 * <p>
1033 * Note that because OpenGL matrices are column-major matrices you must
1034 * transpose the matrix before using it. However, since the matrix is a
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 * rotation matrix, its transpose is also its inverse, conveniently, it is
1036 * often the inverse of the rotation that is needed for rendering; it can
1037 * therefore be used with OpenGL ES directly.
1038 * <p>
1039 * Also note that the returned matrices always have this form:
Mathias Agopian0f791a72010-06-22 21:55:01 -07001040 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 * <pre>
1042 * / M[ 0] M[ 1] M[ 2] 0 \
1043 * | M[ 4] M[ 5] M[ 6] 0 |
1044 * | M[ 8] M[ 9] M[10] 0 |
1045 * \ 0 0 0 1 /
1046 *</pre>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001047 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001048 * <p>
1049 * <u>If the array length is 9:</u>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001050 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 * <pre>
1052 * / M[ 0] M[ 1] M[ 2] \
1053 * | M[ 3] M[ 4] M[ 5] |
1054 * \ M[ 6] M[ 7] M[ 8] /
1055 *</pre>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001056 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 * <hr>
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001058 * <p>
1059 * The inverse of each matrix can be computed easily by taking its
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060 * transpose.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001061 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001062 * <p>
1063 * The matrices returned by this function are meaningful only when the
1064 * device is not free-falling and it is not close to the magnetic north. If
1065 * the device is accelerating, or placed into a strong magnetic field, the
1066 * returned matrices may be inaccurate.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001067 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001068 * @param R
1069 * is an array of 9 floats holding the rotation matrix <b>R</b> when
1070 * this function returns. R can be null.
1071 * <p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001072 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001073 * @param I
1074 * is an array of 9 floats holding the rotation matrix <b>I</b> when
1075 * this function returns. I can be null.
1076 * <p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001077 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001078 * @param gravity
1079 * is an array of 3 floats containing the gravity vector expressed in
1080 * the device's coordinate. You can simply use the
1081 * {@link android.hardware.SensorEvent#values values} returned by a
1082 * {@link android.hardware.SensorEvent SensorEvent} of a
1083 * {@link android.hardware.Sensor Sensor} of type
1084 * {@link android.hardware.Sensor#TYPE_ACCELEROMETER
1085 * TYPE_ACCELEROMETER}.
1086 * <p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001087 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001088 * @param geomagnetic
1089 * is an array of 3 floats containing the geomagnetic vector
1090 * expressed in the device's coordinate. You can simply use the
1091 * {@link android.hardware.SensorEvent#values values} returned by a
1092 * {@link android.hardware.SensorEvent SensorEvent} of a
1093 * {@link android.hardware.Sensor Sensor} of type
1094 * {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD
1095 * TYPE_MAGNETIC_FIELD}.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001096 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001097 * @return <code>true</code> on success, <code>false</code> on failure (for
Peng Xuca09d8c2015-05-21 18:06:06 -07001098 * instance, if the device is in free fall). Free fall is defined as
1099 * condition when the magnitude of the gravity is less than 1/10 of
1100 * the nominal value. On failure the output matrices are not modified.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001101 *
1102 * @see #getInclination(float[])
1103 * @see #getOrientation(float[], float[])
1104 * @see #remapCoordinateSystem(float[], int, int, float[])
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 */
1106
1107 public static boolean getRotationMatrix(float[] R, float[] I,
1108 float[] gravity, float[] geomagnetic) {
1109 // TODO: move this to native code for efficiency
1110 float Ax = gravity[0];
1111 float Ay = gravity[1];
1112 float Az = gravity[2];
Peng Xuca09d8c2015-05-21 18:06:06 -07001113
1114 final float normsqA = (Ax*Ax + Ay*Ay + Az*Az);
1115 final float g = 9.81f;
1116 final float freeFallGravitySquared = 0.01f * g * g;
1117 if (normsqA < freeFallGravitySquared) {
1118 // gravity less than 10% of normal value
1119 return false;
1120 }
1121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122 final float Ex = geomagnetic[0];
1123 final float Ey = geomagnetic[1];
1124 final float Ez = geomagnetic[2];
1125 float Hx = Ey*Az - Ez*Ay;
1126 float Hy = Ez*Ax - Ex*Az;
1127 float Hz = Ex*Ay - Ey*Ax;
1128 final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
Peng Xuca09d8c2015-05-21 18:06:06 -07001129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 if (normH < 0.1f) {
1131 // device is close to free fall (or in space?), or close to
1132 // magnetic north pole. Typical values are > 100.
1133 return false;
1134 }
1135 final float invH = 1.0f / normH;
1136 Hx *= invH;
1137 Hy *= invH;
1138 Hz *= invH;
1139 final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
1140 Ax *= invA;
1141 Ay *= invA;
1142 Az *= invA;
1143 final float Mx = Ay*Hz - Az*Hy;
1144 final float My = Az*Hx - Ax*Hz;
1145 final float Mz = Ax*Hy - Ay*Hx;
1146 if (R != null) {
1147 if (R.length == 9) {
1148 R[0] = Hx; R[1] = Hy; R[2] = Hz;
1149 R[3] = Mx; R[4] = My; R[5] = Mz;
1150 R[6] = Ax; R[7] = Ay; R[8] = Az;
1151 } else if (R.length == 16) {
1152 R[0] = Hx; R[1] = Hy; R[2] = Hz; R[3] = 0;
1153 R[4] = Mx; R[5] = My; R[6] = Mz; R[7] = 0;
1154 R[8] = Ax; R[9] = Ay; R[10] = Az; R[11] = 0;
1155 R[12] = 0; R[13] = 0; R[14] = 0; R[15] = 1;
1156 }
1157 }
1158 if (I != null) {
1159 // compute the inclination matrix by projecting the geomagnetic
1160 // vector onto the Z (gravity) and X (horizontal component
1161 // of geomagnetic vector) axes.
1162 final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
1163 final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
1164 final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
1165 if (I.length == 9) {
1166 I[0] = 1; I[1] = 0; I[2] = 0;
1167 I[3] = 0; I[4] = c; I[5] = s;
1168 I[6] = 0; I[7] =-s; I[8] = c;
1169 } else if (I.length == 16) {
1170 I[0] = 1; I[1] = 0; I[2] = 0;
1171 I[4] = 0; I[5] = c; I[6] = s;
1172 I[8] = 0; I[9] =-s; I[10]= c;
1173 I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
1174 I[15] = 1;
1175 }
1176 }
1177 return true;
1178 }
1179
1180 /**
1181 * Computes the geomagnetic inclination angle in radians from the
1182 * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001183 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001184 * @param I
1185 * inclination matrix see {@link #getRotationMatrix}.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001186 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187 * @return The geomagnetic inclination angle in radians.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001188 *
1189 * @see #getRotationMatrix(float[], float[], float[], float[])
1190 * @see #getOrientation(float[], float[])
1191 * @see GeomagneticField
1192 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001193 */
1194 public static float getInclination(float[] I) {
1195 if (I.length == 9) {
1196 return (float)Math.atan2(I[5], I[4]);
1197 } else {
Mathias Agopian0f791a72010-06-22 21:55:01 -07001198 return (float)Math.atan2(I[6], I[5]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 }
1200 }
1201
1202 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001203 * <p>
1204 * Rotates the supplied rotation matrix so it is expressed in a different
1205 * coordinate system. This is typically used when an application needs to
1206 * compute the three orientation angles of the device (see
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001207 * {@link #getOrientation}) in a different coordinate system.
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001208 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001209 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001210 * <p>
1211 * When the rotation matrix is used for drawing (for instance with OpenGL
1212 * ES), it usually <b>doesn't need</b> to be transformed by this function,
1213 * unless the screen is physically rotated, in which case you can use
1214 * {@link android.view.Display#getRotation() Display.getRotation()} to
1215 * retrieve the current rotation of the screen. Note that because the user
1216 * is generally free to rotate their screen, you often should consider the
1217 * rotation in deciding the parameters to use here.
1218 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001219 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001220 * <p>
1221 * <u>Examples:</u>
1222 * <p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001223 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001224 * <ul>
1225 * <li>Using the camera (Y axis along the camera's axis) for an augmented
1226 * reality application where the rotation angles are needed:</li>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001227 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001228 * <p>
1229 * <ul>
1230 * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code>
1231 * </ul>
1232 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001233 *
Dianne Hackborn5cb70b52010-02-25 17:01:14 -08001234 * <li>Using the device as a mechanical compass when rotation is
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001235 * {@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:</li>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001236 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001237 * <p>
1238 * <ul>
1239 * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code>
1240 * </ul>
1241 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001242 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001243 * Beware of the above example. This call is needed only to account for a
1244 * rotation from its natural orientation when calculating the rotation
1245 * angles (see {@link #getOrientation}). If the rotation matrix is also used
1246 * for rendering, it may not need to be transformed, for instance if your
1247 * {@link android.app.Activity Activity} is running in landscape mode.
1248 * </ul>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001249 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001250 * <p>
1251 * Since the resulting coordinate system is orthonormal, only two axes need
1252 * to be specified.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001253 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001254 * @param inR
1255 * the rotation matrix to be transformed. Usually it is the matrix
1256 * returned by {@link #getRotationMatrix}.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001257 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001258 * @param X
Peng Xuca09d8c2015-05-21 18:06:06 -07001259 * defines the axis of the new cooridinate system that coincide with the X axis of the
1260 * original coordinate system.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001261 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001262 * @param Y
Peng Xuca09d8c2015-05-21 18:06:06 -07001263 * defines the axis of the new cooridinate system that coincide with the Y axis of the
1264 * original coordinate system.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001265 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001266 * @param outR
Katie McCormickf2ef28d2013-11-26 11:10:54 -08001267 * the transformed rotation matrix. inR and outR should not be the same
1268 * array.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001269 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001270 * @return <code>true</code> on success. <code>false</code> if the input
1271 * parameters are incorrect, for instance if X and Y define the same
1272 * axis. Or if inR and outR don't have the same length.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001273 *
1274 * @see #getRotationMatrix(float[], float[], float[], float[])
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001275 */
1276
1277 public static boolean remapCoordinateSystem(float[] inR, int X, int Y,
1278 float[] outR)
1279 {
1280 if (inR == outR) {
1281 final float[] temp = mTempMatrix;
1282 synchronized(temp) {
1283 // we don't expect to have a lot of contention
1284 if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
1285 final int size = outR.length;
1286 for (int i=0 ; i<size ; i++)
1287 outR[i] = temp[i];
1288 return true;
1289 }
1290 }
1291 }
1292 return remapCoordinateSystemImpl(inR, X, Y, outR);
1293 }
1294
1295 private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y,
1296 float[] outR)
1297 {
1298 /*
1299 * X and Y define a rotation matrix 'r':
1300 *
1301 * (X==1)?((X&0x80)?-1:1):0 (X==2)?((X&0x80)?-1:1):0 (X==3)?((X&0x80)?-1:1):0
1302 * (Y==1)?((Y&0x80)?-1:1):0 (Y==2)?((Y&0x80)?-1:1):0 (Y==3)?((X&0x80)?-1:1):0
1303 * r[0] ^ r[1]
1304 *
1305 * where the 3rd line is the vector product of the first 2 lines
1306 *
1307 */
1308
1309 final int length = outR.length;
1310 if (inR.length != length)
1311 return false; // invalid parameter
1312 if ((X & 0x7C)!=0 || (Y & 0x7C)!=0)
1313 return false; // invalid parameter
1314 if (((X & 0x3)==0) || ((Y & 0x3)==0))
1315 return false; // no axis specified
1316 if ((X & 0x3) == (Y & 0x3))
1317 return false; // same axis specified
1318
1319 // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
1320 // this can be calculated by exclusive-or'ing X and Y; except for
1321 // the sign inversion (+/-) which is calculated below.
1322 int Z = X ^ Y;
1323
1324 // extract the axis (remove the sign), offset in the range 0 to 2.
1325 final int x = (X & 0x3)-1;
1326 final int y = (Y & 0x3)-1;
1327 final int z = (Z & 0x3)-1;
1328
1329 // compute the sign of Z (whether it needs to be inverted)
1330 final int axis_y = (z+1)%3;
1331 final int axis_z = (z+2)%3;
1332 if (((x^axis_y)|(y^axis_z)) != 0)
1333 Z ^= 0x80;
1334
1335 final boolean sx = (X>=0x80);
1336 final boolean sy = (Y>=0x80);
1337 final boolean sz = (Z>=0x80);
1338
1339 // Perform R * r, in avoiding actual muls and adds.
1340 final int rowLength = ((length==16)?4:3);
1341 for (int j=0 ; j<3 ; j++) {
1342 final int offset = j*rowLength;
1343 for (int i=0 ; i<3 ; i++) {
1344 if (x==i) outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0];
1345 if (y==i) outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1];
1346 if (z==i) outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2];
1347 }
1348 }
1349 if (length == 16) {
1350 outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
1351 outR[15] = 1;
1352 }
1353 return true;
1354 }
1355
1356 /**
1357 * Computes the device's orientation based on the rotation matrix.
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001358 * <p>
Kevin Hufnagleb4839de2016-04-25 13:33:53 -07001359 * When it returns, the array values are as follows:
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001360 * <ul>
Kevin Hufnagleb4839de2016-04-25 13:33:53 -07001361 * <li>values[0]: <i>Azimuth</i>, angle of rotation about the -z axis.
1362 * This value represents the angle between the device's y
1363 * axis and the magnetic north pole. When facing north, this
1364 * angle is 0, when facing south, this angle is &pi;.
1365 * Likewise, when facing east, this angle is &pi;/2, and
1366 * when facing west, this angle is -&pi;/2. The range of
1367 * values is -&pi; to &pi;.</li>
1368 * <li>values[1]: <i>Pitch</i>, angle of rotation about the x axis.
1369 * This value represents the angle between a plane parallel
1370 * to the device's screen and a plane parallel to the ground.
1371 * Assuming that the bottom edge of the device faces the
1372 * user and that the screen is face-up, tilting the top edge
1373 * of the device toward the ground creates a positive pitch
1374 * angle. The range of values is -&pi; to &pi;.</li>
1375 * <li>values[2]: <i>Roll</i>, angle of rotation about the y axis. This
1376 * value represents the angle between a plane perpendicular
1377 * to the device's screen and a plane perpendicular to the
1378 * ground. Assuming that the bottom edge of the device faces
1379 * the user and that the screen is face-up, tilting the left
1380 * edge of the device toward the ground creates a positive
1381 * roll angle. The range of values is -&pi;/2 to &pi;/2.</li>
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001382 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 * <p>
Kevin Hufnagleb4839de2016-04-25 13:33:53 -07001384 * Applying these three rotations in the azimuth, pitch, roll order
1385 * transforms an identity matrix to the rotation matrix passed into this
1386 * method. Also, note that all three orientation angles are expressed in
1387 * <b>radians</b>.
Aravind Akellab4c76b12013-06-27 12:04:16 -07001388 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001389 * @param R
1390 * rotation matrix see {@link #getRotationMatrix}.
Aravind Akellab4c76b12013-06-27 12:04:16 -07001391 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001392 * @param values
1393 * an array of 3 floats to hold the result.
Aravind Akellab4c76b12013-06-27 12:04:16 -07001394 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395 * @return The array values passed as argument.
Aravind Akellab4c76b12013-06-27 12:04:16 -07001396 *
Mathias Agopian0f791a72010-06-22 21:55:01 -07001397 * @see #getRotationMatrix(float[], float[], float[], float[])
1398 * @see GeomagneticField
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 */
Mathias Agopian04d7e83e2010-07-29 17:59:58 -07001400 public static float[] getOrientation(float[] R, float values[]) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401 /*
1402 * 4x4 (length=16) case:
1403 * / R[ 0] R[ 1] R[ 2] 0 \
1404 * | R[ 4] R[ 5] R[ 6] 0 |
1405 * | R[ 8] R[ 9] R[10] 0 |
1406 * \ 0 0 0 1 /
Mathias Agopian0f791a72010-06-22 21:55:01 -07001407 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 * 3x3 (length=9) case:
1409 * / R[ 0] R[ 1] R[ 2] \
1410 * | R[ 3] R[ 4] R[ 5] |
1411 * \ R[ 6] R[ 7] R[ 8] /
Mathias Agopian0f791a72010-06-22 21:55:01 -07001412 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 */
1414 if (R.length == 9) {
1415 values[0] = (float)Math.atan2(R[1], R[4]);
1416 values[1] = (float)Math.asin(-R[7]);
1417 values[2] = (float)Math.atan2(-R[6], R[8]);
1418 } else {
1419 values[0] = (float)Math.atan2(R[1], R[5]);
1420 values[1] = (float)Math.asin(-R[9]);
1421 values[2] = (float)Math.atan2(-R[8], R[10]);
1422 }
Peng Xuca09d8c2015-05-21 18:06:06 -07001423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 return values;
1425 }
1426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 /**
Mathias Agopian04d7e83e2010-07-29 17:59:58 -07001428 * Computes the Altitude in meters from the atmospheric pressure and the
1429 * pressure at sea level.
1430 * <p>
1431 * Typically the atmospheric pressure is read from a
1432 * {@link Sensor#TYPE_PRESSURE} sensor. The pressure at sea level must be
1433 * known, usually it can be retrieved from airport databases in the
Mathias Agopiana6704d32010-08-18 12:00:30 -07001434 * vicinity. If unknown, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE}
1435 * as an approximation, but absolute altitudes won't be accurate.
1436 * </p>
1437 * <p>
1438 * To calculate altitude differences, you must calculate the difference
1439 * between the altitudes at both points. If you don't know the altitude
1440 * as sea level, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE} instead,
1441 * which will give good results considering the range of pressure typically
1442 * involved.
1443 * </p>
1444 * <p>
1445 * <code><ul>
1446 * float altitude_difference =
1447 * getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point2)
1448 * - getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point1);
1449 * </ul></code>
Mathias Agopian04d7e83e2010-07-29 17:59:58 -07001450 * </p>
1451 *
1452 * @param p0 pressure at sea level
1453 * @param p atmospheric pressure
1454 * @return Altitude in meters
1455 */
Jeff Brown25157e42012-04-16 12:13:05 -07001456 public static float getAltitude(float p0, float p) {
Mathias Agopian04d7e83e2010-07-29 17:59:58 -07001457 final float coef = 1.0f / 5.255f;
1458 return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef));
1459 }
1460
Kevin Powell7a0541d2010-07-19 19:10:40 -07001461 /** Helper function to compute the angle change between two rotation matrices.
1462 * Given a current rotation matrix (R) and a previous rotation matrix
Peng Xuca09d8c2015-05-21 18:06:06 -07001463 * (prevR) computes the intrinsic rotation around the z, x, and y axes which
Kevin Powell7a0541d2010-07-19 19:10:40 -07001464 * transforms prevR to R.
Peng Xuca09d8c2015-05-21 18:06:06 -07001465 * outputs a 3 element vector containing the z, x, and y angle
Kevin Powell7a0541d2010-07-19 19:10:40 -07001466 * change at indexes 0, 1, and 2 respectively.
1467 * <p> Each input matrix is either as a 3x3 or 4x4 row-major matrix
1468 * depending on the length of the passed array:
1469 * <p>If the array length is 9, then the array elements represent this matrix
1470 * <pre>
1471 * / R[ 0] R[ 1] R[ 2] \
1472 * | R[ 3] R[ 4] R[ 5] |
1473 * \ R[ 6] R[ 7] R[ 8] /
1474 *</pre>
1475 * <p>If the array length is 16, then the array elements represent this matrix
1476 * <pre>
1477 * / R[ 0] R[ 1] R[ 2] R[ 3] \
1478 * | R[ 4] R[ 5] R[ 6] R[ 7] |
1479 * | R[ 8] R[ 9] R[10] R[11] |
1480 * \ R[12] R[13] R[14] R[15] /
1481 *</pre>
Peng Xuca09d8c2015-05-21 18:06:06 -07001482 *
1483 * See {@link #getOrientation} for more detailed definition of the output.
1484 *
Kevin Powell7a0541d2010-07-19 19:10:40 -07001485 * @param R current rotation matrix
1486 * @param prevR previous rotation matrix
Peng Xuca09d8c2015-05-21 18:06:06 -07001487 * @param angleChange an an array of floats (z, x, and y) in which the angle change
1488 * (in radians) is stored
Kevin Powell7a0541d2010-07-19 19:10:40 -07001489 */
1490
1491 public static void getAngleChange( float[] angleChange, float[] R, float[] prevR) {
1492 float rd1=0,rd4=0, rd6=0,rd7=0, rd8=0;
1493 float ri0=0,ri1=0,ri2=0,ri3=0,ri4=0,ri5=0,ri6=0,ri7=0,ri8=0;
1494 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 -07001495
1496 if(R.length == 9) {
1497 ri0 = R[0];
1498 ri1 = R[1];
1499 ri2 = R[2];
1500 ri3 = R[3];
1501 ri4 = R[4];
1502 ri5 = R[5];
1503 ri6 = R[6];
1504 ri7 = R[7];
1505 ri8 = R[8];
1506 } else if(R.length == 16) {
1507 ri0 = R[0];
1508 ri1 = R[1];
1509 ri2 = R[2];
1510 ri3 = R[4];
1511 ri4 = R[5];
1512 ri5 = R[6];
1513 ri6 = R[8];
1514 ri7 = R[9];
1515 ri8 = R[10];
1516 }
1517
1518 if(prevR.length == 9) {
Kevin Powell34884b42010-11-03 16:04:30 -07001519 pri0 = prevR[0];
1520 pri1 = prevR[1];
1521 pri2 = prevR[2];
1522 pri3 = prevR[3];
1523 pri4 = prevR[4];
1524 pri5 = prevR[5];
1525 pri6 = prevR[6];
1526 pri7 = prevR[7];
1527 pri8 = prevR[8];
Kevin Powell7a0541d2010-07-19 19:10:40 -07001528 } else if(prevR.length == 16) {
Kevin Powell34884b42010-11-03 16:04:30 -07001529 pri0 = prevR[0];
1530 pri1 = prevR[1];
1531 pri2 = prevR[2];
1532 pri3 = prevR[4];
1533 pri4 = prevR[5];
1534 pri5 = prevR[6];
1535 pri6 = prevR[8];
1536 pri7 = prevR[9];
1537 pri8 = prevR[10];
Kevin Powell7a0541d2010-07-19 19:10:40 -07001538 }
1539
1540 // calculate the parts of the rotation difference matrix we need
1541 // rd[i][j] = pri[0][i] * ri[0][j] + pri[1][i] * ri[1][j] + pri[2][i] * ri[2][j];
1542
1543 rd1 = pri0 * ri1 + pri3 * ri4 + pri6 * ri7; //rd[0][1]
1544 rd4 = pri1 * ri1 + pri4 * ri4 + pri7 * ri7; //rd[1][1]
1545 rd6 = pri2 * ri0 + pri5 * ri3 + pri8 * ri6; //rd[2][0]
1546 rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1]
1547 rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2]
1548
1549 angleChange[0] = (float)Math.atan2(rd1, rd4);
1550 angleChange[1] = (float)Math.asin(-rd7);
1551 angleChange[2] = (float)Math.atan2(-rd6, rd8);
1552
1553 }
1554
1555 /** Helper function to convert a rotation vector to a rotation matrix.
1556 * Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a
1557 * 9 or 16 element rotation matrix in the array R. R must have length 9 or 16.
1558 * If R.length == 9, the following matrix is returned:
1559 * <pre>
1560 * / R[ 0] R[ 1] R[ 2] \
1561 * | R[ 3] R[ 4] R[ 5] |
1562 * \ R[ 6] R[ 7] R[ 8] /
1563 *</pre>
1564 * If R.length == 16, the following matrix is returned:
1565 * <pre>
1566 * / R[ 0] R[ 1] R[ 2] 0 \
1567 * | R[ 4] R[ 5] R[ 6] 0 |
1568 * | R[ 8] R[ 9] R[10] 0 |
1569 * \ 0 0 0 1 /
1570 *</pre>
1571 * @param rotationVector the rotation vector to convert
1572 * @param R an array of floats in which to store the rotation matrix
1573 */
1574 public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) {
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001575
1576 float q0;
Kevin Powell7a0541d2010-07-19 19:10:40 -07001577 float q1 = rotationVector[0];
1578 float q2 = rotationVector[1];
1579 float q3 = rotationVector[2];
1580
Balint Ureczky12d39b92013-12-05 00:03:45 +01001581 if (rotationVector.length >= 4) {
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001582 q0 = rotationVector[3];
1583 } else {
Mathias Agopian7b6e4bd62011-02-14 16:34:07 -08001584 q0 = 1 - q1*q1 - q2*q2 - q3*q3;
1585 q0 = (q0 > 0) ? (float)Math.sqrt(q0) : 0;
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001586 }
1587
Kevin Powell7a0541d2010-07-19 19:10:40 -07001588 float sq_q1 = 2 * q1 * q1;
1589 float sq_q2 = 2 * q2 * q2;
1590 float sq_q3 = 2 * q3 * q3;
1591 float q1_q2 = 2 * q1 * q2;
1592 float q3_q0 = 2 * q3 * q0;
1593 float q1_q3 = 2 * q1 * q3;
1594 float q2_q0 = 2 * q2 * q0;
1595 float q2_q3 = 2 * q2 * q3;
1596 float q1_q0 = 2 * q1 * q0;
1597
1598 if(R.length == 9) {
1599 R[0] = 1 - sq_q2 - sq_q3;
1600 R[1] = q1_q2 - q3_q0;
1601 R[2] = q1_q3 + q2_q0;
1602
1603 R[3] = q1_q2 + q3_q0;
1604 R[4] = 1 - sq_q1 - sq_q3;
1605 R[5] = q2_q3 - q1_q0;
1606
1607 R[6] = q1_q3 - q2_q0;
1608 R[7] = q2_q3 + q1_q0;
1609 R[8] = 1 - sq_q1 - sq_q2;
1610 } else if (R.length == 16) {
1611 R[0] = 1 - sq_q2 - sq_q3;
1612 R[1] = q1_q2 - q3_q0;
1613 R[2] = q1_q3 + q2_q0;
1614 R[3] = 0.0f;
1615
1616 R[4] = q1_q2 + q3_q0;
1617 R[5] = 1 - sq_q1 - sq_q3;
1618 R[6] = q2_q3 - q1_q0;
1619 R[7] = 0.0f;
1620
1621 R[8] = q1_q3 - q2_q0;
1622 R[9] = q2_q3 + q1_q0;
1623 R[10] = 1 - sq_q1 - sq_q2;
1624 R[11] = 0.0f;
1625
1626 R[12] = R[13] = R[14] = 0.0f;
1627 R[15] = 1.0f;
1628 }
1629 }
1630
1631 /** Helper function to convert a rotation vector to a normalized quaternion.
1632 * Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a normalized
1633 * quaternion in the array Q. The quaternion is stored as [w, x, y, z]
1634 * @param rv the rotation vector to convert
1635 * @param Q an array of floats in which to store the computed quaternion
1636 */
1637 public static void getQuaternionFromVector(float[] Q, float[] rv) {
Balint Ureczky12d39b92013-12-05 00:03:45 +01001638 if (rv.length >= 4) {
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001639 Q[0] = rv[3];
1640 } else {
Mathias Agopian0eab8212011-03-07 17:49:54 -08001641 Q[0] = 1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2];
1642 Q[0] = (Q[0] > 0) ? (float)Math.sqrt(Q[0]) : 0;
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001643 }
Kevin Powell7a0541d2010-07-19 19:10:40 -07001644 Q[1] = rv[0];
1645 Q[2] = rv[1];
1646 Q[3] = rv[2];
1647 }
1648
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -08001649 /**
1650 * Requests receiving trigger events for a trigger sensor.
1651 *
1652 * <p>
1653 * When the sensor detects a trigger event condition, such as significant motion in
1654 * the case of the {@link Sensor#TYPE_SIGNIFICANT_MOTION}, the provided trigger listener
1655 * will be invoked once and then its request to receive trigger events will be canceled.
1656 * To continue receiving trigger events, the application must request to receive trigger
1657 * events again.
1658 * </p>
1659 *
1660 * @param listener The listener on which the
1661 * {@link TriggerEventListener#onTrigger(TriggerEvent)} will be delivered.
1662 * @param sensor The sensor to be enabled.
1663 *
1664 * @return true if the sensor was successfully enabled.
1665 *
1666 * @throws IllegalArgumentException when sensor is null or not a trigger sensor.
1667 */
1668 public boolean requestTriggerSensor(TriggerEventListener listener, Sensor sensor) {
1669 return requestTriggerSensorImpl(listener, sensor);
1670 }
1671
1672 /**
1673 * @hide
1674 */
1675 protected abstract boolean requestTriggerSensorImpl(TriggerEventListener listener,
1676 Sensor sensor);
1677
1678 /**
1679 * Cancels receiving trigger events for a trigger sensor.
1680 *
1681 * <p>
1682 * Note that a Trigger sensor will be auto disabled if
1683 * {@link TriggerEventListener#onTrigger(TriggerEvent)} has triggered.
1684 * This method is provided in case the user wants to explicitly cancel the request
1685 * to receive trigger events.
1686 * </p>
1687 *
1688 * @param listener The listener on which the
1689 * {@link TriggerEventListener#onTrigger(TriggerEvent)}
1690 * is delivered.It should be the same as the one used
1691 * in {@link #requestTriggerSensor(TriggerEventListener, Sensor)}
1692 * @param sensor The sensor for which the trigger request should be canceled.
1693 * If null, it cancels receiving trigger for all sensors associated
1694 * with the listener.
1695 *
1696 * @return true if successfully canceled.
1697 *
1698 * @throws IllegalArgumentException when sensor is a trigger sensor.
1699 */
1700 public boolean cancelTriggerSensor(TriggerEventListener listener, Sensor sensor) {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -07001701 return cancelTriggerSensorImpl(listener, sensor, true);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -08001702 }
1703
1704 /**
1705 * @hide
1706 */
1707 protected abstract boolean cancelTriggerSensorImpl(TriggerEventListener listener,
Jaikumar Ganesh2e900892013-04-11 10:40:33 -07001708 Sensor sensor, boolean disable);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -08001709
1710
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001711 /**
1712 * For testing purposes only. Not for third party applications.
1713 *
Aravind Akellad123b512015-06-29 12:35:51 -07001714 * Initialize data injection mode and create a client for data injection. SensorService should
1715 * already be operating in DATA_INJECTION mode for this call succeed. To set SensorService into
1716 * DATA_INJECTION mode "adb shell dumpsys sensorservice data_injection" needs to be called
1717 * through adb. Typically this is done using a host side test. This mode is expected to be used
1718 * only for testing purposes. If the HAL is set to data injection mode, it will ignore the input
1719 * from physical sensors and read sensor data that is injected from the test application. This
1720 * mode is used for testing vendor implementations for various algorithms like Rotation Vector,
1721 * Significant Motion, Step Counter etc. Not all HALs support DATA_INJECTION. This method will
1722 * fail in those cases. Once this method succeeds, the test can call
1723 * {@link injectSensorData(Sensor, float[], int, long)} to inject sensor data into the HAL.
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001724 *
Aravind Akellad123b512015-06-29 12:35:51 -07001725 * @param enable True to initialize a client in DATA_INJECTION mode.
1726 * False to clean up the native resources.
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001727 *
1728 * @return true if the HAL supports data injection and false
1729 * otherwise.
1730 * @hide
1731 */
1732 @SystemApi
Aravind Akellad123b512015-06-29 12:35:51 -07001733 public boolean initDataInjection(boolean enable) {
1734 return initDataInjectionImpl(enable);
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001735 }
1736
1737 /**
1738 * @hide
1739 */
Aravind Akellad123b512015-06-29 12:35:51 -07001740 protected abstract boolean initDataInjectionImpl(boolean enable);
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001741
1742 /**
1743 * For testing purposes only. Not for third party applications.
1744 *
Aravind Akellad123b512015-06-29 12:35:51 -07001745 * This method is used to inject raw sensor data into the HAL. Call {@link
1746 * initDataInjection(boolean)} before this method to set the HAL in data injection mode. This
1747 * method should be called only if a previous call to initDataInjection has been successful and
1748 * the HAL and SensorService are already opreating in data injection mode.
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001749 *
1750 * @param sensor The sensor to inject.
1751 * @param values Sensor values to inject. The length of this
1752 * array must be exactly equal to the number of
1753 * values reported by the sensor type.
1754 * @param accuracy Accuracy of the sensor.
1755 * @param timestamp Sensor timestamp associated with the event.
1756 *
1757 * @return boolean True if the data injection succeeds, false
1758 * otherwise.
1759 * @throws IllegalArgumentException when the sensor is null,
1760 * data injection is not supported by the sensor, values
1761 * are null, incorrect number of values for the sensor,
1762 * sensor accuracy is incorrect or timestamps are
1763 * invalid.
1764 * @hide
1765 */
1766 @SystemApi
1767 public boolean injectSensorData(Sensor sensor, float[] values, int accuracy,
1768 long timestamp) {
1769 if (sensor == null) {
1770 throw new IllegalArgumentException("sensor cannot be null");
1771 }
1772 if (!sensor.isDataInjectionSupported()) {
1773 throw new IllegalArgumentException("sensor does not support data injection");
1774 }
1775 if (values == null) {
1776 throw new IllegalArgumentException("sensor data cannot be null");
1777 }
Dianne Hackborn0e3de6c2015-07-29 15:20:21 -07001778 int expectedNumValues = Sensor.getMaxLengthValuesArray(sensor, Build.VERSION_CODES.M);
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001779 if (values.length != expectedNumValues) {
1780 throw new IllegalArgumentException ("Wrong number of values for sensor " +
1781 sensor.getName() + " actual=" + values.length + " expected=" +
1782 expectedNumValues);
1783 }
1784 if (accuracy < SENSOR_STATUS_NO_CONTACT || accuracy > SENSOR_STATUS_ACCURACY_HIGH) {
1785 throw new IllegalArgumentException("Invalid sensor accuracy");
1786 }
1787 if (timestamp <= 0) {
1788 throw new IllegalArgumentException("Negative or zero sensor timestamp");
1789 }
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001790 return injectSensorDataImpl(sensor, values, accuracy, timestamp);
1791 }
1792
1793 /**
1794 * @hide
1795 */
1796 protected abstract boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
1797 long timestamp);
1798
Jeff Brown4481d9c2012-04-16 16:14:44 -07001799 private LegacySensorManager getLegacySensorManager() {
1800 synchronized (mSensorListByType) {
1801 if (mLegacySensorManager == null) {
1802 Log.i(TAG, "This application is using deprecated SensorManager API which will "
1803 + "be removed someday. Please consider switching to the new API.");
1804 mLegacySensorManager = new LegacySensorManager(this);
Jeff Brown25157e42012-04-16 12:13:05 -07001805 }
Jeff Brown4481d9c2012-04-16 16:14:44 -07001806 return mLegacySensorManager;
Jeff Brown25157e42012-04-16 12:13:05 -07001807 }
1808 }
Aravind Akellab4c76b12013-06-27 12:04:16 -07001809
1810 private static int getDelay(int rate) {
1811 int delay = -1;
1812 switch (rate) {
1813 case SENSOR_DELAY_FASTEST:
1814 delay = 0;
1815 break;
1816 case SENSOR_DELAY_GAME:
1817 delay = 20000;
1818 break;
1819 case SENSOR_DELAY_UI:
1820 delay = 66667;
1821 break;
1822 case SENSOR_DELAY_NORMAL:
1823 delay = 200000;
1824 break;
1825 default:
1826 delay = rate;
1827 break;
1828 }
1829 return delay;
1830 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001831}