blob: 6bf754f6935e3a4f693eb8e2b4bbe0c3a07fe8c0 [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;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060020import android.annotation.SystemService;
Artur Satayev26958002019-12-10 17:47:52 +000021import android.compat.annotation.UnsupportedAppUsage;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060022import android.content.Context;
Aravind Akella18ebf732b2015-04-20 17:39:51 -070023import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.os.Handler;
Peng Xuccf0c8e2017-01-17 22:16:21 -080025import android.os.MemoryFile;
Jeff Brown4481d9c2012-04-16 16:14:44 -070026import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.util.SparseArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import java.util.ArrayList;
30import java.util.Collections;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import java.util.List;
32
33/**
Mathias Agopian43c87e42010-08-25 14:35:54 -070034 * <p>
Mathias Agopian74cde2c2010-06-16 18:55:46 -070035 * SensorManager lets you access the device's {@link android.hardware.Sensor
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060036 * sensors}.
Mathias Agopian43c87e42010-08-25 14:35:54 -070037 * </p>
38 * <p>
39 * Always make sure to disable sensors you don't need, especially when your
40 * activity is paused. Failing to do so can drain the battery in just a few
41 * hours. Note that the system will <i>not</i> disable sensors automatically when
42 * the screen turns off.
43 * </p>
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -080044 * <p class="note">
45 * Note: Don't use this mechanism with a Trigger Sensor, have a look
46 * at {@link TriggerEventListener}. {@link Sensor#TYPE_SIGNIFICANT_MOTION}
47 * is an example of a trigger sensor.
48 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -070049 * <pre class="prettyprint">
Greg Kaiserac823732016-02-26 16:37:01 -080050 * public class SensorActivity extends Activity implements SensorEventListener {
Mathias Agopian0f791a72010-06-22 21:55:01 -070051 * private final SensorManager mSensorManager;
52 * private final Sensor mAccelerometer;
53 *
54 * public SensorActivity() {
55 * mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
56 * mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Mathias Agopian43c87e42010-08-25 14:35:54 -070057 * }
58 *
59 * protected void onResume() {
60 * super.onResume();
Mathias Agopian0f791a72010-06-22 21:55:01 -070061 * mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
62 * }
63 *
Mathias Agopian43c87e42010-08-25 14:35:54 -070064 * protected void onPause() {
65 * super.onPause();
66 * mSensorManager.unregisterListener(this);
67 * }
68 *
Mathias Agopian0f791a72010-06-22 21:55:01 -070069 * public void onAccuracyChanged(Sensor sensor, int accuracy) {
70 * }
71 *
Mathias Agopian43c87e42010-08-25 14:35:54 -070072 * public void onSensorChanged(SensorEvent event) {
Mathias Agopian0f791a72010-06-22 21:55:01 -070073 * }
74 * }
75 * </pre>
76 *
77 * @see SensorEventListener
78 * @see SensorEvent
79 * @see Sensor
80 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060082@SystemService(Context.SENSOR_SERVICE)
Jeff Brown25157e42012-04-16 12:13:05 -070083public abstract class SensorManager {
Jeff Brown4481d9c2012-04-16 16:14:44 -070084 /** @hide */
85 protected static final String TAG = "SensorManager";
86
Peng Xu62f2c872017-09-22 11:50:33 -070087 private static final float[] sTempMatrix = new float[16];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088
Jeff Brown25157e42012-04-16 12:13:05 -070089 // Cached lists of sensors by type. Guarded by mSensorListByType.
90 private final SparseArray<List<Sensor>> mSensorListByType =
91 new SparseArray<List<Sensor>>();
92
Jeff Brown4481d9c2012-04-16 16:14:44 -070093 // Legacy sensor manager implementation. Guarded by mSensorListByType during initialization.
94 private LegacySensorManager mLegacySensorManager;
95
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 /* NOTE: sensor IDs must be a power of 2 */
97
98 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -070099 * A constant describing an orientation sensor. See
100 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700101 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
103 */
104 @Deprecated
105 public static final int SENSOR_ORIENTATION = 1 << 0;
106
107 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700108 * A constant describing an accelerometer. See
109 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700110 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
112 */
113 @Deprecated
114 public static final int SENSOR_ACCELEROMETER = 1 << 1;
115
116 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700117 * A constant describing a temperature sensor See
118 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700119 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
121 */
122 @Deprecated
123 public static final int SENSOR_TEMPERATURE = 1 << 2;
124
125 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700126 * A constant describing a magnetic sensor See
127 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700128 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
130 */
131 @Deprecated
132 public static final int SENSOR_MAGNETIC_FIELD = 1 << 3;
133
134 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700135 * A constant describing an ambient light sensor See
136 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700137 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
139 */
140 @Deprecated
141 public static final int SENSOR_LIGHT = 1 << 4;
142
143 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700144 * A constant describing a proximity sensor See
145 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700146 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
148 */
149 @Deprecated
150 public static final int SENSOR_PROXIMITY = 1 << 5;
151
152 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700153 * A constant describing a Tricorder See
154 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700155 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
157 */
158 @Deprecated
159 public static final int SENSOR_TRICORDER = 1 << 6;
160
161 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700162 * A constant describing an orientation sensor. See
163 * {@link android.hardware.SensorListener SensorListener} for more details.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700164 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
166 */
167 @Deprecated
168 public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
169
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700170 /**
171 * A constant that includes all sensors
Mathias Agopian0f791a72010-06-22 21:55:01 -0700172 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700173 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
174 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 @Deprecated
176 public static final int SENSOR_ALL = 0x7F;
177
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700178 /**
179 * Smallest sensor ID
Mathias Agopian0f791a72010-06-22 21:55:01 -0700180 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700181 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
182 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 @Deprecated
184 public static final int SENSOR_MIN = SENSOR_ORIENTATION;
185
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700186 /**
187 * Largest sensor ID
Mathias Agopian0f791a72010-06-22 21:55:01 -0700188 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700189 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
190 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 @Deprecated
Peng Xu62f2c872017-09-22 11:50:33 -0700192 public static final int SENSOR_MAX = ((SENSOR_ALL + 1) >> 1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193
194
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700195 /**
196 * Index of the X value in the array returned by
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700197 * {@link android.hardware.SensorListener#onSensorChanged}
Mathias Agopian0f791a72010-06-22 21:55:01 -0700198 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700199 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
200 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 @Deprecated
202 public static final int DATA_X = 0;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700203
204 /**
205 * Index of the Y value in the array returned by
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700206 * {@link android.hardware.SensorListener#onSensorChanged}
Mathias Agopian0f791a72010-06-22 21:55:01 -0700207 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700208 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
209 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 @Deprecated
211 public static final int DATA_Y = 1;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700212
213 /**
214 * Index of the Z value in the array returned by
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700215 * {@link android.hardware.SensorListener#onSensorChanged}
Mathias Agopian0f791a72010-06-22 21:55:01 -0700216 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700217 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
218 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 @Deprecated
220 public static final int DATA_Z = 2;
221
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700222 /**
223 * Offset to the untransformed values in the array returned by
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700224 * {@link android.hardware.SensorListener#onSensorChanged}
Mathias Agopian0f791a72010-06-22 21:55:01 -0700225 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700226 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
227 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 @Deprecated
229 public static final int RAW_DATA_INDEX = 3;
230
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700231 /**
232 * Index of the untransformed X value in the array returned by
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700233 * {@link android.hardware.SensorListener#onSensorChanged}
Mathias Agopian0f791a72010-06-22 21:55:01 -0700234 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700235 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
236 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 @Deprecated
238 public static final int RAW_DATA_X = 3;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700239
240 /**
241 * Index of the untransformed Y value in the array returned by
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700242 * {@link android.hardware.SensorListener#onSensorChanged}
Mathias Agopian0f791a72010-06-22 21:55:01 -0700243 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700244 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
245 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 @Deprecated
247 public static final int RAW_DATA_Y = 4;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700248
249 /**
250 * Index of the untransformed Z value in the array returned by
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700251 * {@link android.hardware.SensorListener#onSensorChanged}
Mathias Agopian0f791a72010-06-22 21:55:01 -0700252 *
Dianne Hackborn4a51c202009-08-21 15:14:02 -0700253 * @deprecated use {@link android.hardware.Sensor Sensor} instead.
254 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 @Deprecated
256 public static final int RAW_DATA_Z = 5;
257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 /** Standard gravity (g) on Earth. This value is equivalent to 1G */
259 public static final float STANDARD_GRAVITY = 9.80665f;
260
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700261 /** Sun's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262 public static final float GRAVITY_SUN = 275.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700263 /** Mercury's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 public static final float GRAVITY_MERCURY = 3.70f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700265 /** Venus' gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 public static final float GRAVITY_VENUS = 8.87f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700267 /** Earth's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 public static final float GRAVITY_EARTH = 9.80665f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700269 /** The Moon's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 public static final float GRAVITY_MOON = 1.6f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700271 /** Mars' gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 public static final float GRAVITY_MARS = 3.71f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700273 /** Jupiter's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 public static final float GRAVITY_JUPITER = 23.12f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700275 /** Saturn's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 public static final float GRAVITY_SATURN = 8.96f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700277 /** Uranus' gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 public static final float GRAVITY_URANUS = 8.69f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700279 /** Neptune's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 public static final float GRAVITY_NEPTUNE = 11.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700281 /** Pluto's gravity in SI units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 public static final float GRAVITY_PLUTO = 0.6f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700283 /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 public static final float GRAVITY_DEATH_STAR_I = 0.000000353036145f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700285 /** Gravity on the island */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 public static final float GRAVITY_THE_ISLAND = 4.815162342f;
287
288
289 /** Maximum magnetic field on Earth's surface */
290 public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 /** Minimum magnetic field on Earth's surface */
292 public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;
293
Mathias Agopian0f791a72010-06-22 21:55:01 -0700294
Mathias Agopian04d7e83e2010-07-29 17:59:58 -0700295 /** Standard atmosphere, or average sea-level pressure in hPa (millibar) */
296 public static final float PRESSURE_STANDARD_ATMOSPHERE = 1013.25f;
297
298
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700299 /** Maximum luminance of sunlight in lux */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700301 /** luminance of sunlight in lux */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 public static final float LIGHT_SUNLIGHT = 110000.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700303 /** luminance in shade in lux */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 public static final float LIGHT_SHADE = 20000.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700305 /** luminance under an overcast sky in lux */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 public static final float LIGHT_OVERCAST = 10000.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700307 /** luminance at sunrise in lux */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 public static final float LIGHT_SUNRISE = 400.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700309 /** luminance under a cloudy sky in lux */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 public static final float LIGHT_CLOUDY = 100.0f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700311 /** luminance at night with full moon in lux */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 public static final float LIGHT_FULLMOON = 0.25f;
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700313 /** luminance at night with no moon in lux*/
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 public static final float LIGHT_NO_MOON = 0.001f;
315
Mathias Agopian0f791a72010-06-22 21:55:01 -0700316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 /** get sensor data as fast as possible */
318 public static final int SENSOR_DELAY_FASTEST = 0;
319 /** rate suitable for games */
320 public static final int SENSOR_DELAY_GAME = 1;
321 /** rate suitable for the user interface */
322 public static final int SENSOR_DELAY_UI = 2;
323 /** rate (default) suitable for screen orientation changes */
324 public static final int SENSOR_DELAY_NORMAL = 3;
325
326
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700327 /**
Etienne Le Grandaf805102014-05-16 12:21:41 -0700328 * The values returned by this sensor cannot be trusted because the sensor
329 * had no contact with what it was measuring (for example, the heart rate
330 * monitor is not in contact with the user).
331 */
332 public static final int SENSOR_STATUS_NO_CONTACT = -1;
333
334 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700335 * The values returned by this sensor cannot be trusted, calibration is
336 * needed or the environment doesn't allow readings
337 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338 public static final int SENSOR_STATUS_UNRELIABLE = 0;
339
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700340 /**
341 * This sensor is reporting data with low accuracy, calibration with the
342 * environment is needed
343 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
345
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700346 /**
347 * This sensor is reporting data with an average level of accuracy,
348 * calibration with the environment may improve the readings
349 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;
351
352 /** This sensor is reporting data with maximum accuracy */
353 public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;
354
355 /** see {@link #remapCoordinateSystem} */
356 public static final int AXIS_X = 1;
357 /** see {@link #remapCoordinateSystem} */
358 public static final int AXIS_Y = 2;
359 /** see {@link #remapCoordinateSystem} */
360 public static final int AXIS_Z = 3;
361 /** see {@link #remapCoordinateSystem} */
362 public static final int AXIS_MINUS_X = AXIS_X | 0x80;
363 /** see {@link #remapCoordinateSystem} */
364 public static final int AXIS_MINUS_Y = AXIS_Y | 0x80;
365 /** see {@link #remapCoordinateSystem} */
366 public static final int AXIS_MINUS_Z = AXIS_Z | 0x80;
367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368
369 /**
370 * {@hide}
371 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100372 @UnsupportedAppUsage
Jeff Brown25157e42012-04-16 12:13:05 -0700373 public SensorManager() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 }
375
Jeff Brown25157e42012-04-16 12:13:05 -0700376 /**
377 * Gets the full list of sensors that are available.
378 * @hide
379 */
380 protected abstract List<Sensor> getFullSensorList();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700382 /**
Peng Xua35b5532016-01-20 00:05:45 -0800383 * Gets the full list of dynamic sensors that are available.
384 * @hide
385 */
386 protected abstract List<Sensor> getFullDynamicSensorList();
387
388 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700389 * @return available sensors.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 * @deprecated This method is deprecated, use
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700391 * {@link SensorManager#getSensorList(int)} instead
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 */
393 @Deprecated
394 public int getSensors() {
Jeff Brown4481d9c2012-04-16 16:14:44 -0700395 return getLegacySensorManager().getSensors();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 }
397
398 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700399 * Use this method to get the list of available sensors of a certain type.
400 * Make multiple calls to get sensors of different types or use
401 * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the
402 * sensors.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700403 *
Aravind Akella0288ca62014-07-28 14:53:44 -0700404 * <p class="note">
405 * NOTE: Both wake-up and non wake-up sensors matching the given type are
406 * returned. Check {@link Sensor#isWakeUpSensor()} to know the wake-up properties
407 * of the returned {@link Sensor}.
408 * </p>
409 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700410 * @param type
411 * of sensors requested
Mathias Agopian0f791a72010-06-22 21:55:01 -0700412 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 * @return a list of sensors matching the asked type.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700414 *
415 * @see #getDefaultSensor(int)
416 * @see Sensor
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 */
418 public List<Sensor> getSensorList(int type) {
419 // cache the returned lists the first time
420 List<Sensor> list;
Jeff Brown25157e42012-04-16 12:13:05 -0700421 final List<Sensor> fullList = getFullSensorList();
422 synchronized (mSensorListByType) {
423 list = mSensorListByType.get(type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800424 if (list == null) {
425 if (type == Sensor.TYPE_ALL) {
426 list = fullList;
427 } else {
428 list = new ArrayList<Sensor>();
429 for (Sensor i : fullList) {
Peng Xu62f2c872017-09-22 11:50:33 -0700430 if (i.getType() == type) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 list.add(i);
Peng Xu62f2c872017-09-22 11:50:33 -0700432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 }
434 }
435 list = Collections.unmodifiableList(list);
Jeff Brown25157e42012-04-16 12:13:05 -0700436 mSensorListByType.append(type, list);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 }
438 }
439 return list;
440 }
441
442 /**
Peng Xua35b5532016-01-20 00:05:45 -0800443 * Use this method to get a list of available dynamic sensors of a certain type.
444 * Make multiple calls to get sensors of different types or use
445 * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all dynamic sensors.
446 *
447 * <p class="note">
448 * NOTE: Both wake-up and non wake-up sensors matching the given type are
449 * returned. Check {@link Sensor#isWakeUpSensor()} to know the wake-up properties
450 * of the returned {@link Sensor}.
451 * </p>
452 *
453 * @param type of sensors requested
454 *
455 * @return a list of dynamic sensors matching the requested type.
456 *
457 * @see Sensor
458 */
459 public List<Sensor> getDynamicSensorList(int type) {
460 // cache the returned lists the first time
461 final List<Sensor> fullList = getFullDynamicSensorList();
462 if (type == Sensor.TYPE_ALL) {
463 return Collections.unmodifiableList(fullList);
464 } else {
465 List<Sensor> list = new ArrayList();
466 for (Sensor i : fullList) {
Peng Xu62f2c872017-09-22 11:50:33 -0700467 if (i.getType() == type) {
Peng Xua35b5532016-01-20 00:05:45 -0800468 list.add(i);
Peng Xu62f2c872017-09-22 11:50:33 -0700469 }
Peng Xua35b5532016-01-20 00:05:45 -0800470 }
471 return Collections.unmodifiableList(list);
472 }
473 }
474
475 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700476 * Use this method to get the default sensor for a given type. Note that the
477 * returned sensor could be a composite sensor, and its data could be
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 * averaged or filtered. If you need to access the raw sensors use
479 * {@link SensorManager#getSensorList(int) getSensorList}.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700480 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700481 * @param type
Etienne Le Grandaf805102014-05-16 12:21:41 -0700482 * of sensors requested
Mathias Agopian0f791a72010-06-22 21:55:01 -0700483 *
Etienne Le Grandaf805102014-05-16 12:21:41 -0700484 * @return the default sensor matching the requested type if one exists and the application
485 * has the necessary permissions, or null otherwise.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700486 *
487 * @see #getSensorList(int)
488 * @see Sensor
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 */
490 public Sensor getDefaultSensor(int type) {
491 // TODO: need to be smarter, for now, just return the 1st sensor
492 List<Sensor> l = getSensorList(type);
Aravind Akella0288ca62014-07-28 14:53:44 -0700493 boolean wakeUpSensor = false;
494 // For the following sensor types, return a wake-up sensor. These types are by default
495 // defined as wake-up sensors. For the rest of the SDK defined sensor types return a
496 // non_wake-up version.
Peng Xu62f2c872017-09-22 11:50:33 -0700497 if (type == Sensor.TYPE_PROXIMITY || type == Sensor.TYPE_SIGNIFICANT_MOTION
498 || type == Sensor.TYPE_TILT_DETECTOR || type == Sensor.TYPE_WAKE_GESTURE
499 || type == Sensor.TYPE_GLANCE_GESTURE || type == Sensor.TYPE_PICK_UP_GESTURE
500 || type == Sensor.TYPE_WRIST_TILT_GESTURE
501 || type == Sensor.TYPE_DYNAMIC_SENSOR_META) {
Aravind Akella0288ca62014-07-28 14:53:44 -0700502 wakeUpSensor = true;
503 }
504
505 for (Sensor sensor : l) {
506 if (sensor.isWakeUpSensor() == wakeUpSensor) return sensor;
507 }
508 return null;
509 }
510
511 /**
512 * Return a Sensor with the given type and wakeUp properties. If multiple sensors of this
513 * type exist, any one of them may be returned.
514 * <p>
515 * For example,
516 * <ul>
Peng Xu62f2c872017-09-22 11:50:33 -0700517 * <li>getDefaultSensor({@link Sensor#TYPE_ACCELEROMETER}, true) returns a wake-up
518 * accelerometer sensor if it exists. </li>
519 * <li>getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, false) returns a non wake-up
520 * proximity sensor if it exists. </li>
521 * <li>getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, true) returns a wake-up proximity
522 * sensor which is the same as the Sensor returned by {@link #getDefaultSensor(int)}. </li>
Aravind Akella0288ca62014-07-28 14:53:44 -0700523 * </ul>
524 * </p>
525 * <p class="note">
526 * Note: Sensors like {@link Sensor#TYPE_PROXIMITY} and {@link Sensor#TYPE_SIGNIFICANT_MOTION}
527 * are declared as wake-up sensors by default.
528 * </p>
529 * @param type
530 * type of sensor requested
531 * @param wakeUp
532 * flag to indicate whether the Sensor is a wake-up or non wake-up sensor.
533 * @return the default sensor matching the requested type and wakeUp properties if one exists
534 * and the application has the necessary permissions, or null otherwise.
535 * @see Sensor#isWakeUpSensor()
536 */
537 public Sensor getDefaultSensor(int type, boolean wakeUp) {
538 List<Sensor> l = getSensorList(type);
539 for (Sensor sensor : l) {
Peng Xu62f2c872017-09-22 11:50:33 -0700540 if (sensor.isWakeUpSensor() == wakeUp) {
Aravind Akella0288ca62014-07-28 14:53:44 -0700541 return sensor;
Peng Xu62f2c872017-09-22 11:50:33 -0700542 }
Aravind Akella0288ca62014-07-28 14:53:44 -0700543 }
544 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 }
546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547 /**
548 * Registers a listener for given sensors.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700549 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 * @deprecated This method is deprecated, use
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700551 * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
552 * instead.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700553 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700554 * @param listener
555 * sensor listener object
Mathias Agopian0f791a72010-06-22 21:55:01 -0700556 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700557 * @param sensors
558 * a bit masks of the sensors to register to
Mathias Agopian0f791a72010-06-22 21:55:01 -0700559 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700560 * @return <code>true</code> if the sensor is supported and successfully
561 * enabled
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562 */
563 @Deprecated
564 public boolean registerListener(SensorListener listener, int sensors) {
565 return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
566 }
567
568 /**
569 * Registers a SensorListener for given sensors.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700570 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 * @deprecated This method is deprecated, use
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700572 * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
573 * instead.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700574 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700575 * @param listener
576 * sensor listener object
Mathias Agopian0f791a72010-06-22 21:55:01 -0700577 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700578 * @param sensors
579 * a bit masks of the sensors to register to
Mathias Agopian0f791a72010-06-22 21:55:01 -0700580 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700581 * @param rate
582 * rate of events. This is only a hint to the system. events may be
583 * received faster or slower than the specified rate. Usually events
584 * are received faster. The value must be one of
585 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
586 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700587 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700588 * @return <code>true</code> if the sensor is supported and successfully
589 * enabled
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 */
591 @Deprecated
592 public boolean registerListener(SensorListener listener, int sensors, int rate) {
Jeff Brown4481d9c2012-04-16 16:14:44 -0700593 return getLegacySensorManager().registerListener(listener, sensors, rate);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 }
595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 /**
597 * Unregisters a listener for all sensors.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700598 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800599 * @deprecated This method is deprecated, use
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700600 * {@link SensorManager#unregisterListener(SensorEventListener)}
601 * instead.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700602 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700603 * @param listener
604 * a SensorListener object
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605 */
606 @Deprecated
607 public void unregisterListener(SensorListener listener) {
608 unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
609 }
610
Jeff Brown4481d9c2012-04-16 16:14:44 -0700611 /**
612 * Unregisters a listener for the sensors with which it is registered.
613 *
614 * @deprecated This method is deprecated, use
615 * {@link SensorManager#unregisterListener(SensorEventListener, Sensor)}
616 * instead.
617 *
618 * @param listener
619 * a SensorListener object
620 *
621 * @param sensors
622 * a bit masks of the sensors to unregister from
623 */
624 @Deprecated
625 public void unregisterListener(SensorListener listener, int sensors) {
626 getLegacySensorManager().unregisterListener(listener, sensors);
Jeff Brown25157e42012-04-16 12:13:05 -0700627 }
628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 /**
630 * Unregisters a listener for the sensors with which it is registered.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700631 *
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800632 * <p class="note"></p>
633 * Note: Don't use this method with a one shot trigger sensor such as
634 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}.
635 * Use {@link #cancelTriggerSensor(TriggerEventListener, Sensor)} instead.
636 * </p>
637 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700638 * @param listener
639 * a SensorEventListener object
Mathias Agopian0f791a72010-06-22 21:55:01 -0700640 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700641 * @param sensor
642 * the sensor to unregister from
Mathias Agopian0f791a72010-06-22 21:55:01 -0700643 *
644 * @see #unregisterListener(SensorEventListener)
645 * @see #registerListener(SensorEventListener, Sensor, int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 */
647 public void unregisterListener(SensorEventListener listener, Sensor sensor) {
Jeff Brown25157e42012-04-16 12:13:05 -0700648 if (listener == null || sensor == null) {
649 return;
650 }
651
652 unregisterListenerImpl(listener, sensor);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653 }
654
655 /**
656 * Unregisters a listener for all sensors.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700657 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -0700658 * @param listener
659 * a SensorListener object
Mathias Agopian0f791a72010-06-22 21:55:01 -0700660 *
661 * @see #unregisterListener(SensorEventListener, Sensor)
662 * @see #registerListener(SensorEventListener, Sensor, int)
663 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664 */
665 public void unregisterListener(SensorEventListener listener) {
Jeff Brown25157e42012-04-16 12:13:05 -0700666 if (listener == null) {
667 return;
668 }
669
670 unregisterListenerImpl(listener, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671 }
672
Jeff Brown25157e42012-04-16 12:13:05 -0700673 /** @hide */
674 protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor sensor);
675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 /**
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700677 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
678 * sensor at the given sampling frequency.
679 * <p>
680 * The events will be delivered to the provided {@code SensorEventListener} as soon as they are
681 * available. To reduce the power consumption, applications can use
682 * {@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a
683 * positive non-zero maximum reporting latency.
684 * </p>
685 * <p>
686 * In the case of non-wake-up sensors, the events are only delivered while the Application
687 * Processor (AP) is not in suspend mode. See {@link Sensor#isWakeUpSensor()} for more details.
688 * To ensure delivery of events from non-wake-up sensors even when the screen is OFF, the
689 * application registering to the sensor must hold a partial wake-lock to keep the AP awake,
690 * otherwise some events might be lost while the AP is asleep. Note that although events might
691 * be lost while the AP is asleep, the sensor will still consume power if it is not explicitly
692 * deactivated by the application. Applications must unregister their {@code
693 * SensorEventListener}s in their activity's {@code onPause()} method to avoid consuming power
694 * while the device is inactive. See {@link #registerListener(SensorEventListener, Sensor, int,
695 * int)} for more details on hardware FIFO (queueing) capabilities and when some sensor events
696 * might be lost.
697 * </p>
698 * <p>
699 * In the case of wake-up sensors, each event generated by the sensor will cause the AP to
700 * wake-up, ensuring that each event can be delivered. Because of this, registering to a wake-up
701 * sensor has very significant power implications. Call {@link Sensor#isWakeUpSensor()} to check
702 * whether a sensor is a wake-up sensor. See
703 * {@link #registerListener(SensorEventListener, Sensor, int, int)} for information on how to
704 * reduce the power impact of registering to wake-up sensors.
705 * </p>
706 * <p class="note">
707 * Note: Don't use this method with one-shot trigger sensors such as
708 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use
709 * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. Use
710 * {@link Sensor#getReportingMode()} to obtain the reporting mode of a given sensor.
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800711 * </p>
712 *
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700713 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object.
714 * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
715 * @param samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are
716 * delivered at. This is only a hint to the system. Events may be received faster or
717 * slower than the specified rate. Usually events are received faster. The value must
718 * be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
719 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired delay
720 * between events in microseconds. Specifying the delay in microseconds only works
721 * from Android 2.3 (API level 9) onwards. For earlier releases, you must use one of
722 * the {@code SENSOR_DELAY_*} constants.
723 * @return <code>true</code> if the sensor is supported and successfully enabled.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700724 * @see #registerListener(SensorEventListener, Sensor, int, Handler)
725 * @see #unregisterListener(SensorEventListener)
726 * @see #unregisterListener(SensorEventListener, Sensor)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 */
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700728 public boolean registerListener(SensorEventListener listener, Sensor sensor,
729 int samplingPeriodUs) {
730 return registerListener(listener, sensor, samplingPeriodUs, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 }
732
733 /**
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700734 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
735 * sensor at the given sampling frequency and the given maximum reporting latency.
Aravind Akellab4c76b12013-06-27 12:04:16 -0700736 * <p>
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700737 * This function is similar to {@link #registerListener(SensorEventListener, Sensor, int)} but
738 * it allows events to stay temporarily in the hardware FIFO (queue) before being delivered. The
739 * events can be stored in the hardware FIFO up to {@code maxReportLatencyUs} microseconds. Once
740 * one of the events in the FIFO needs to be reported, all of the events in the FIFO are
741 * reported sequentially. This means that some events will be reported before the maximum
742 * reporting latency has elapsed.
743 * </p><p>
744 * When {@code maxReportLatencyUs} is 0, the call is equivalent to a call to
745 * {@link #registerListener(SensorEventListener, Sensor, int)}, as it requires the events to be
746 * delivered as soon as possible.
747 * </p><p>
748 * When {@code sensor.maxFifoEventCount()} is 0, the sensor does not use a FIFO, so the call
749 * will also be equivalent to {@link #registerListener(SensorEventListener, Sensor, int)}.
750 * </p><p>
751 * Setting {@code maxReportLatencyUs} to a positive value allows to reduce the number of
752 * interrupts the AP (Application Processor) receives, hence reducing power consumption, as the
753 * AP can switch to a lower power state while the sensor is capturing the data. This is
754 * especially important when registering to wake-up sensors, for which each interrupt causes the
755 * AP to wake up if it was in suspend mode. See {@link Sensor#isWakeUpSensor()} for more
756 * information on wake-up sensors.
Aravind Akellab4c76b12013-06-27 12:04:16 -0700757 * </p>
758 * <p class="note">
759 * </p>
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700760 * Note: Don't use this method with one-shot trigger sensors such as
Aravind Akellab4c76b12013-06-27 12:04:16 -0700761 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use
762 * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p>
763 *
764 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700765 * that will receive the sensor events. If the application is interested in receiving
766 * flush complete notifications, it should register with
767 * {@link android.hardware.SensorEventListener SensorEventListener2} instead.
Aravind Akellab4c76b12013-06-27 12:04:16 -0700768 * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700769 * @param samplingPeriodUs The desired delay between two consecutive events in microseconds.
770 * This is only a hint to the system. Events may be received faster or slower than
771 * the specified rate. Usually events are received faster. Can be one of
Aravind Akellab4c76b12013-06-27 12:04:16 -0700772 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
773 * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in
774 * microseconds.
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700775 * @param maxReportLatencyUs Maximum time in microseconds that events can be delayed before
776 * being reported to the application. A large value allows reducing the power
777 * consumption associated with the sensor. If maxReportLatencyUs is set to zero,
778 * events are delivered as soon as they are available, which is equivalent to calling
Aravind Akellab4c76b12013-06-27 12:04:16 -0700779 * {@link #registerListener(SensorEventListener, Sensor, int)}.
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700780 * @return <code>true</code> if the sensor is supported and successfully enabled.
Aravind Akellab4c76b12013-06-27 12:04:16 -0700781 * @see #registerListener(SensorEventListener, Sensor, int)
782 * @see #unregisterListener(SensorEventListener)
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700783 * @see #flush(SensorEventListener)
Aravind Akellab4c76b12013-06-27 12:04:16 -0700784 */
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700785 public boolean registerListener(SensorEventListener listener, Sensor sensor,
786 int samplingPeriodUs, int maxReportLatencyUs) {
787 int delay = getDelay(samplingPeriodUs);
788 return registerListenerImpl(listener, sensor, delay, null, maxReportLatencyUs, 0);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700789 }
790
791 /**
792 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
Aravind Akellad405e0f2013-09-04 12:07:33 -0700793 * sensor. Events are delivered in continuous mode as soon as they are available. To reduce the
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700794 * power consumption, applications can use
795 * {@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a
796 * positive non-zero maximum reporting latency.
797 * <p class="note">
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800798 * </p>
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700799 * Note: Don't use this method with a one shot trigger sensor such as
800 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use
801 * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p>
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800802 *
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700803 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object.
804 * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
805 * @param samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are
806 * delivered at. This is only a hint to the system. Events may be received faster or
807 * slower than the specified rate. Usually events are received faster. The value must
808 * be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
809 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired
810 * delay between events in microseconds. Specifying the delay in microseconds only
811 * works from Android 2.3 (API level 9) onwards. For earlier releases, you must use
812 * one of the {@code SENSOR_DELAY_*} constants.
813 * @param handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent
814 * sensor events} will be delivered to.
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700815 * @return <code>true</code> if the sensor is supported and successfully enabled.
Mathias Agopian0f791a72010-06-22 21:55:01 -0700816 * @see #registerListener(SensorEventListener, Sensor, int)
817 * @see #unregisterListener(SensorEventListener)
818 * @see #unregisterListener(SensorEventListener, Sensor)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 */
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700820 public boolean registerListener(SensorEventListener listener, Sensor sensor,
821 int samplingPeriodUs, Handler handler) {
822 int delay = getDelay(samplingPeriodUs);
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700823 return registerListenerImpl(listener, sensor, delay, handler, 0, 0);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825
Aravind Akellab4c76b12013-06-27 12:04:16 -0700826 /**
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700827 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
828 * sensor at the given sampling frequency and the given maximum reporting latency.
829 *
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700830 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
831 * that will receive the sensor events. If the application is interested in receiving
832 * flush complete notifications, it should register with
833 * {@link android.hardware.SensorEventListener SensorEventListener2} instead.
834 * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700835 * @param samplingPeriodUs The desired delay between two consecutive events in microseconds.
836 * This is only a hint to the system. Events may be received faster or slower than
837 * the specified rate. Usually events are received faster. Can be one of
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700838 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
839 * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in
840 * microseconds.
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700841 * @param maxReportLatencyUs Maximum time in microseconds that events can be delayed before
842 * being reported to the application. A large value allows reducing the power
843 * consumption associated with the sensor. If maxReportLatencyUs is set to zero,
844 * events are delivered as soon as they are available, which is equivalent to calling
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700845 * {@link #registerListener(SensorEventListener, Sensor, int)}.
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700846 * @param handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent
847 * sensor events} will be delivered to.
848 * @return <code>true</code> if the sensor is supported and successfully enabled.
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700849 * @see #registerListener(SensorEventListener, Sensor, int, int)
Aravind Akellab4c76b12013-06-27 12:04:16 -0700850 */
Peng Xu62f2c872017-09-22 11:50:33 -0700851 public boolean registerListener(SensorEventListener listener, Sensor sensor,
852 int samplingPeriodUs, int maxReportLatencyUs, Handler handler) {
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700853 int delayUs = getDelay(samplingPeriodUs);
854 return registerListenerImpl(listener, sensor, delayUs, handler, maxReportLatencyUs, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 }
856
Jeff Brown25157e42012-04-16 12:13:05 -0700857 /** @hide */
858 protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700859 int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700860
861
862 /**
Aravind Akella1f9b32f2014-09-16 15:21:44 -0700863 * Flushes the FIFO of all the sensors registered for this listener. If there are events
864 * in the FIFO of the sensor, they are returned as if the maxReportLantecy of the FIFO has
865 * expired. Events are returned in the usual way through the SensorEventListener.
866 * This call doesn't affect the maxReportLantecy for this sensor. This call is asynchronous and
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700867 * returns immediately.
868 * {@link android.hardware.SensorEventListener2#onFlushCompleted onFlushCompleted} is called
869 * after all the events in the batch at the time of calling this method have been delivered
870 * successfully. If the hardware doesn't support flush, it still returns true and a trivial
871 * flush complete event is sent after the current event for all the clients registered for this
872 * sensor.
873 *
874 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
875 * which was previously used in a registerListener call.
876 * @return <code>true</code> if the flush is initiated successfully on all the sensors
877 * registered for this listener, false if no sensor is previously registered for this
878 * listener or flush on one of the sensors fails.
879 * @see #registerListener(SensorEventListener, Sensor, int, int)
880 * @throws IllegalArgumentException when listener is null.
Aravind Akellab4c76b12013-06-27 12:04:16 -0700881 */
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700882 public boolean flush(SensorEventListener listener) {
883 return flushImpl(listener);
Aravind Akellab4c76b12013-06-27 12:04:16 -0700884 }
885
886 /** @hide */
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700887 protected abstract boolean flushImpl(SensorEventListener listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800888
Peng Xua35b5532016-01-20 00:05:45 -0800889
890 /**
Peng Xu3c8c6a42017-04-06 18:37:56 -0700891 * Create a sensor direct channel backed by shared memory wrapped in MemoryFile object.
892 *
893 * The resulting channel can be used for delivering sensor events to native code, other
894 * processes, GPU/DSP or other co-processors without CPU intervention. This is the recommanded
895 * for high performance sensor applications that use high sensor rates (e.g. greater than 200Hz)
896 * and cares about sensor event latency.
Peng Xuccf0c8e2017-01-17 22:16:21 -0800897 *
898 * Use the returned {@link android.hardware.SensorDirectChannel} object to configure direct
899 * report of sensor events. After use, call {@link android.hardware.SensorDirectChannel#close()}
900 * to free up resource in sensor system associated with the direct channel.
901 *
902 * @param mem A {@link android.os.MemoryFile} shared memory object.
Peng Xu9ee042e2017-07-05 15:21:12 -0700903 * @return A {@link android.hardware.SensorDirectChannel} object.
Peng Xu3c8c6a42017-04-06 18:37:56 -0700904 * @throws NullPointerException when mem is null.
Peng Xu9ee042e2017-07-05 15:21:12 -0700905 * @throws UncheckedIOException if not able to create channel.
Peng Xuccf0c8e2017-01-17 22:16:21 -0800906 * @see SensorDirectChannel#close()
Peng Xuccf0c8e2017-01-17 22:16:21 -0800907 */
908 public SensorDirectChannel createDirectChannel(MemoryFile mem) {
Peng Xu7d96fa02017-03-04 16:15:45 -0800909 return createDirectChannelImpl(mem, null);
Peng Xuccf0c8e2017-01-17 22:16:21 -0800910 }
911
912 /**
Peng Xu3c8c6a42017-04-06 18:37:56 -0700913 * Create a sensor direct channel backed by shared memory wrapped in HardwareBuffer object.
914 *
915 * The resulting channel can be used for delivering sensor events to native code, other
916 * processes, GPU/DSP or other co-processors without CPU intervention. This is the recommanded
917 * for high performance sensor applications that use high sensor rates (e.g. greater than 200Hz)
918 * and cares about sensor event latency.
Peng Xuccf0c8e2017-01-17 22:16:21 -0800919 *
920 * Use the returned {@link android.hardware.SensorDirectChannel} object to configure direct
921 * report of sensor events. After use, call {@link android.hardware.SensorDirectChannel#close()}
922 * to free up resource in sensor system associated with the direct channel.
923 *
924 * @param mem A {@link android.hardware.HardwareBuffer} shared memory object.
Peng Xu9ee042e2017-07-05 15:21:12 -0700925 * @return A {@link android.hardware.SensorDirectChannel} object.
Peng Xu3c8c6a42017-04-06 18:37:56 -0700926 * @throws NullPointerException when mem is null.
Peng Xu9ee042e2017-07-05 15:21:12 -0700927 * @throws UncheckedIOException if not able to create channel.
Peng Xuccf0c8e2017-01-17 22:16:21 -0800928 * @see SensorDirectChannel#close()
Peng Xuccf0c8e2017-01-17 22:16:21 -0800929 */
930 public SensorDirectChannel createDirectChannel(HardwareBuffer mem) {
Peng Xu7d96fa02017-03-04 16:15:45 -0800931 return createDirectChannelImpl(null, mem);
Peng Xuccf0c8e2017-01-17 22:16:21 -0800932 }
933
934 /** @hide */
Peng Xu7d96fa02017-03-04 16:15:45 -0800935 protected abstract SensorDirectChannel createDirectChannelImpl(
936 MemoryFile memoryFile, HardwareBuffer hardwareBuffer);
Peng Xufa2672b2016-12-07 03:54:44 -0800937
938 /** @hide */
Peng Xuccf0c8e2017-01-17 22:16:21 -0800939 void destroyDirectChannel(SensorDirectChannel channel) {
Peng Xufa2672b2016-12-07 03:54:44 -0800940 destroyDirectChannelImpl(channel);
Peng Xuccf0c8e2017-01-17 22:16:21 -0800941 }
942
Peng Xufa2672b2016-12-07 03:54:44 -0800943 /** @hide */
944 protected abstract void destroyDirectChannelImpl(SensorDirectChannel channel);
945
Peng Xufa2672b2016-12-07 03:54:44 -0800946 /** @hide */
947 protected abstract int configureDirectChannelImpl(
948 SensorDirectChannel channel, Sensor s, int rate);
949
Peng Xuccf0c8e2017-01-17 22:16:21 -0800950 /**
Peng Xua35b5532016-01-20 00:05:45 -0800951 * Used for receiving notifications from the SensorManager when dynamic sensors are connected or
952 * disconnected.
953 */
Peng Xu62f2c872017-09-22 11:50:33 -0700954 public abstract static class DynamicSensorCallback {
Peng Xua35b5532016-01-20 00:05:45 -0800955 /**
956 * Called when there is a dynamic sensor being connected to the system.
957 *
958 * @param sensor the newly connected sensor. See {@link android.hardware.Sensor Sensor}.
959 */
960 public void onDynamicSensorConnected(Sensor sensor) {}
961
962 /**
963 * Called when there is a dynamic sensor being disconnected from the system.
964 *
965 * @param sensor the disconnected sensor. See {@link android.hardware.Sensor Sensor}.
966 */
967 public void onDynamicSensorDisconnected(Sensor sensor) {}
968 }
969
970
971 /**
Peng Xufb1c9412016-03-29 21:50:43 -0700972 * Add a {@link android.hardware.SensorManager.DynamicSensorCallback
973 * DynamicSensorCallback} to receive dynamic sensor connection callbacks. Repeat
Peng Xua35b5532016-01-20 00:05:45 -0800974 * registration with the already registered callback object will have no additional effect.
975 *
976 * @param callback An object that implements the
Peng Xufb1c9412016-03-29 21:50:43 -0700977 * {@link android.hardware.SensorManager.DynamicSensorCallback
978 * DynamicSensorCallback}
Peng Xua35b5532016-01-20 00:05:45 -0800979 * interface for receiving callbacks.
Aurimas Liutikas7f695332018-05-31 21:07:32 -0700980 * @see #registerDynamicSensorCallback(DynamicSensorCallback, Handler)
Peng Xua35b5532016-01-20 00:05:45 -0800981 *
982 * @throws IllegalArgumentException when callback is null.
983 */
Peng Xufb1c9412016-03-29 21:50:43 -0700984 public void registerDynamicSensorCallback(DynamicSensorCallback callback) {
Peng Xua35b5532016-01-20 00:05:45 -0800985 registerDynamicSensorCallback(callback, null);
986 }
987
988 /**
Peng Xufb1c9412016-03-29 21:50:43 -0700989 * Add a {@link android.hardware.SensorManager.DynamicSensorCallback
990 * DynamicSensorCallback} to receive dynamic sensor connection callbacks. Repeat
Peng Xua35b5532016-01-20 00:05:45 -0800991 * registration with the already registered callback object will have no additional effect.
992 *
993 * @param callback An object that implements the
Peng Xufb1c9412016-03-29 21:50:43 -0700994 * {@link android.hardware.SensorManager.DynamicSensorCallback
995 * DynamicSensorCallback} interface for receiving callbacks.
Peng Xua35b5532016-01-20 00:05:45 -0800996 * @param handler The {@link android.os.Handler Handler} the {@link
Peng Xufb1c9412016-03-29 21:50:43 -0700997 * android.hardware.SensorManager.DynamicSensorCallback
Peng Xua35b5532016-01-20 00:05:45 -0800998 * sensor connection events} will be delivered to.
999 *
1000 * @throws IllegalArgumentException when callback is null.
1001 */
1002 public void registerDynamicSensorCallback(
Peng Xufb1c9412016-03-29 21:50:43 -07001003 DynamicSensorCallback callback, Handler handler) {
Peng Xua35b5532016-01-20 00:05:45 -08001004 registerDynamicSensorCallbackImpl(callback, handler);
1005 }
1006
1007 /**
Peng Xufb1c9412016-03-29 21:50:43 -07001008 * Remove a {@link android.hardware.SensorManager.DynamicSensorCallback
1009 * DynamicSensorCallback} to stop sending dynamic sensor connection events to that
Peng Xua35b5532016-01-20 00:05:45 -08001010 * callback.
1011 *
1012 * @param callback An object that implements the
Peng Xufb1c9412016-03-29 21:50:43 -07001013 * {@link android.hardware.SensorManager.DynamicSensorCallback
1014 * DynamicSensorCallback}
Peng Xua35b5532016-01-20 00:05:45 -08001015 * interface for receiving callbacks.
1016 */
Peng Xufb1c9412016-03-29 21:50:43 -07001017 public void unregisterDynamicSensorCallback(DynamicSensorCallback callback) {
Peng Xua35b5532016-01-20 00:05:45 -08001018 unregisterDynamicSensorCallbackImpl(callback);
1019 }
1020
Peng Xufb1c9412016-03-29 21:50:43 -07001021 /**
1022 * Tell if dynamic sensor discovery feature is supported by system.
1023 *
1024 * @return <code>true</code> if dynamic sensor discovery is supported, <code>false</code>
1025 * otherwise.
1026 */
1027 public boolean isDynamicSensorDiscoverySupported() {
1028 List<Sensor> sensors = getSensorList(Sensor.TYPE_DYNAMIC_SENSOR_META);
1029 return sensors.size() > 0;
1030 }
1031
Peng Xua35b5532016-01-20 00:05:45 -08001032 /** @hide */
1033 protected abstract void registerDynamicSensorCallbackImpl(
Peng Xufb1c9412016-03-29 21:50:43 -07001034 DynamicSensorCallback callback, Handler handler);
Peng Xua35b5532016-01-20 00:05:45 -08001035
1036 /** @hide */
1037 protected abstract void unregisterDynamicSensorCallbackImpl(
Peng Xufb1c9412016-03-29 21:50:43 -07001038 DynamicSensorCallback callback);
Peng Xua35b5532016-01-20 00:05:45 -08001039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001041 * <p>
1042 * Computes the inclination matrix <b>I</b> as well as the rotation matrix
1043 * <b>R</b> transforming a vector from the device coordinate system to the
1044 * world's coordinate system which is defined as a direct orthonormal basis,
1045 * where:
1046 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001047 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001048 * <ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
1050 * the ground at the device's current location and roughly points East).</li>
1051 * <li>Y is tangential to the ground at the device's current location and
1052 * points towards the magnetic North Pole.</li>
1053 * <li>Z points towards the sky and is perpendicular to the ground.</li>
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001054 * </ul>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001055 *
1056 * <p>
1057 * <center><img src="../../../images/axis_globe.png"
Mathias Agopianf71384c2010-11-19 16:25:11 -08001058 * alt="World coordinate-system diagram." border="0" /></center>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001059 * </p>
1060 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061 * <p>
1062 * <hr>
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001063 * <p>
1064 * By definition:
1065 * <p>
1066 * [0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity)
1067 * <p>
1068 * [0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b> (m = magnitude of
1069 * geomagnetic field)
1070 * <p>
1071 * <b>R</b> is the identity matrix when the device is aligned with the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 * world's coordinate system, that is, when the device's X axis points
1073 * toward East, the Y axis points to the North Pole and the device is facing
1074 * the sky.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001075 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001076 * <p>
1077 * <b>I</b> is a rotation matrix transforming the geomagnetic vector into
1078 * the same coordinate space as gravity (the world's coordinate space).
1079 * <b>I</b> is a simple rotation around the X axis. The inclination angle in
1080 * radians can be computed with {@link #getInclination}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 * <hr>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001082 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001083 * <p>
1084 * Each matrix is returned either as a 3x3 or 4x4 row-major matrix depending
1085 * on the length of the passed array:
1086 * <p>
1087 * <u>If the array length is 16:</u>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001088 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 * <pre>
1090 * / M[ 0] M[ 1] M[ 2] M[ 3] \
1091 * | M[ 4] M[ 5] M[ 6] M[ 7] |
1092 * | M[ 8] M[ 9] M[10] M[11] |
1093 * \ M[12] M[13] M[14] M[15] /
1094 *</pre>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001095 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001096 * This matrix is ready to be used by OpenGL ES's
1097 * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int)
1098 * glLoadMatrixf(float[], int)}.
1099 * <p>
1100 * Note that because OpenGL matrices are column-major matrices you must
1101 * transpose the matrix before using it. However, since the matrix is a
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 * rotation matrix, its transpose is also its inverse, conveniently, it is
1103 * often the inverse of the rotation that is needed for rendering; it can
1104 * therefore be used with OpenGL ES directly.
1105 * <p>
1106 * Also note that the returned matrices always have this form:
Mathias Agopian0f791a72010-06-22 21:55:01 -07001107 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 * <pre>
1109 * / M[ 0] M[ 1] M[ 2] 0 \
1110 * | M[ 4] M[ 5] M[ 6] 0 |
1111 * | M[ 8] M[ 9] M[10] 0 |
1112 * \ 0 0 0 1 /
1113 *</pre>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001114 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001115 * <p>
1116 * <u>If the array length is 9:</u>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001117 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 * <pre>
1119 * / M[ 0] M[ 1] M[ 2] \
1120 * | M[ 3] M[ 4] M[ 5] |
1121 * \ M[ 6] M[ 7] M[ 8] /
1122 *</pre>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001123 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 * <hr>
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001125 * <p>
1126 * The inverse of each matrix can be computed easily by taking its
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 * transpose.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001128 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001129 * <p>
1130 * The matrices returned by this function are meaningful only when the
1131 * device is not free-falling and it is not close to the magnetic north. If
1132 * the device is accelerating, or placed into a strong magnetic field, the
1133 * returned matrices may be inaccurate.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001134 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001135 * @param R
1136 * is an array of 9 floats holding the rotation matrix <b>R</b> when
1137 * this function returns. R can be null.
1138 * <p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001139 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001140 * @param I
1141 * is an array of 9 floats holding the rotation matrix <b>I</b> when
1142 * this function returns. I can be null.
1143 * <p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001144 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001145 * @param gravity
1146 * is an array of 3 floats containing the gravity vector expressed in
1147 * the device's coordinate. You can simply use the
1148 * {@link android.hardware.SensorEvent#values values} returned by a
1149 * {@link android.hardware.SensorEvent SensorEvent} of a
1150 * {@link android.hardware.Sensor Sensor} of type
1151 * {@link android.hardware.Sensor#TYPE_ACCELEROMETER
1152 * TYPE_ACCELEROMETER}.
1153 * <p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001154 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001155 * @param geomagnetic
1156 * is an array of 3 floats containing the geomagnetic vector
1157 * expressed in the device's coordinate. You can simply use the
1158 * {@link android.hardware.SensorEvent#values values} returned by a
1159 * {@link android.hardware.SensorEvent SensorEvent} of a
1160 * {@link android.hardware.Sensor Sensor} of type
1161 * {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD
1162 * TYPE_MAGNETIC_FIELD}.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001163 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001164 * @return <code>true</code> on success, <code>false</code> on failure (for
Peng Xuca09d8c2015-05-21 18:06:06 -07001165 * instance, if the device is in free fall). Free fall is defined as
1166 * condition when the magnitude of the gravity is less than 1/10 of
1167 * the nominal value. On failure the output matrices are not modified.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001168 *
1169 * @see #getInclination(float[])
1170 * @see #getOrientation(float[], float[])
1171 * @see #remapCoordinateSystem(float[], int, int, float[])
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 */
1173
1174 public static boolean getRotationMatrix(float[] R, float[] I,
1175 float[] gravity, float[] geomagnetic) {
1176 // TODO: move this to native code for efficiency
1177 float Ax = gravity[0];
1178 float Ay = gravity[1];
1179 float Az = gravity[2];
Peng Xuca09d8c2015-05-21 18:06:06 -07001180
Peng Xu62f2c872017-09-22 11:50:33 -07001181 final float normsqA = (Ax * Ax + Ay * Ay + Az * Az);
Peng Xuca09d8c2015-05-21 18:06:06 -07001182 final float g = 9.81f;
1183 final float freeFallGravitySquared = 0.01f * g * g;
1184 if (normsqA < freeFallGravitySquared) {
1185 // gravity less than 10% of normal value
1186 return false;
1187 }
1188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 final float Ex = geomagnetic[0];
1190 final float Ey = geomagnetic[1];
1191 final float Ez = geomagnetic[2];
Peng Xu62f2c872017-09-22 11:50:33 -07001192 float Hx = Ey * Az - Ez * Ay;
1193 float Hy = Ez * Ax - Ex * Az;
1194 float Hz = Ex * Ay - Ey * Ax;
1195 final float normH = (float) Math.sqrt(Hx * Hx + Hy * Hy + Hz * Hz);
Peng Xuca09d8c2015-05-21 18:06:06 -07001196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 if (normH < 0.1f) {
1198 // device is close to free fall (or in space?), or close to
1199 // magnetic north pole. Typical values are > 100.
1200 return false;
1201 }
1202 final float invH = 1.0f / normH;
1203 Hx *= invH;
1204 Hy *= invH;
1205 Hz *= invH;
Peng Xu62f2c872017-09-22 11:50:33 -07001206 final float invA = 1.0f / (float) Math.sqrt(Ax * Ax + Ay * Ay + Az * Az);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001207 Ax *= invA;
1208 Ay *= invA;
1209 Az *= invA;
Peng Xu62f2c872017-09-22 11:50:33 -07001210 final float Mx = Ay * Hz - Az * Hy;
1211 final float My = Az * Hx - Ax * Hz;
1212 final float Mz = Ax * Hy - Ay * Hx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001213 if (R != null) {
1214 if (R.length == 9) {
1215 R[0] = Hx; R[1] = Hy; R[2] = Hz;
1216 R[3] = Mx; R[4] = My; R[5] = Mz;
1217 R[6] = Ax; R[7] = Ay; R[8] = Az;
1218 } else if (R.length == 16) {
1219 R[0] = Hx; R[1] = Hy; R[2] = Hz; R[3] = 0;
1220 R[4] = Mx; R[5] = My; R[6] = Mz; R[7] = 0;
1221 R[8] = Ax; R[9] = Ay; R[10] = Az; R[11] = 0;
1222 R[12] = 0; R[13] = 0; R[14] = 0; R[15] = 1;
1223 }
1224 }
1225 if (I != null) {
1226 // compute the inclination matrix by projecting the geomagnetic
1227 // vector onto the Z (gravity) and X (horizontal component
1228 // of geomagnetic vector) axes.
Peng Xu62f2c872017-09-22 11:50:33 -07001229 final float invE = 1.0f / (float) Math.sqrt(Ex * Ex + Ey * Ey + Ez * Ez);
1230 final float c = (Ex * Mx + Ey * My + Ez * Mz) * invE;
1231 final float s = (Ex * Ax + Ey * Ay + Ez * Az) * invE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232 if (I.length == 9) {
1233 I[0] = 1; I[1] = 0; I[2] = 0;
1234 I[3] = 0; I[4] = c; I[5] = s;
Peng Xu62f2c872017-09-22 11:50:33 -07001235 I[6] = 0; I[7] = -s; I[8] = c;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 } else if (I.length == 16) {
1237 I[0] = 1; I[1] = 0; I[2] = 0;
1238 I[4] = 0; I[5] = c; I[6] = s;
Peng Xu62f2c872017-09-22 11:50:33 -07001239 I[8] = 0; I[9] = -s; I[10] = c;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240 I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
1241 I[15] = 1;
1242 }
1243 }
1244 return true;
1245 }
1246
1247 /**
1248 * Computes the geomagnetic inclination angle in radians from the
1249 * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001250 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001251 * @param I
1252 * inclination matrix see {@link #getRotationMatrix}.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001253 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001254 * @return The geomagnetic inclination angle in radians.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001255 *
1256 * @see #getRotationMatrix(float[], float[], float[], float[])
1257 * @see #getOrientation(float[], float[])
1258 * @see GeomagneticField
1259 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 */
1261 public static float getInclination(float[] I) {
1262 if (I.length == 9) {
Peng Xu62f2c872017-09-22 11:50:33 -07001263 return (float) Math.atan2(I[5], I[4]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264 } else {
Peng Xu62f2c872017-09-22 11:50:33 -07001265 return (float) Math.atan2(I[6], I[5]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001266 }
1267 }
1268
1269 /**
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001270 * <p>
1271 * Rotates the supplied rotation matrix so it is expressed in a different
1272 * coordinate system. This is typically used when an application needs to
1273 * compute the three orientation angles of the device (see
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001274 * {@link #getOrientation}) in a different coordinate system.
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001275 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001276 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001277 * <p>
1278 * When the rotation matrix is used for drawing (for instance with OpenGL
1279 * ES), it usually <b>doesn't need</b> to be transformed by this function,
1280 * unless the screen is physically rotated, in which case you can use
1281 * {@link android.view.Display#getRotation() Display.getRotation()} to
1282 * retrieve the current rotation of the screen. Note that because the user
1283 * is generally free to rotate their screen, you often should consider the
1284 * rotation in deciding the parameters to use here.
1285 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001286 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001287 * <p>
1288 * <u>Examples:</u>
1289 * <p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001290 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001291 * <ul>
1292 * <li>Using the camera (Y axis along the camera's axis) for an augmented
1293 * reality application where the rotation angles are needed:</li>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001294 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001295 * <p>
1296 * <ul>
1297 * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code>
1298 * </ul>
1299 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001300 *
Dianne Hackborn5cb70b52010-02-25 17:01:14 -08001301 * <li>Using the device as a mechanical compass when rotation is
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001302 * {@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:</li>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001303 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001304 * <p>
1305 * <ul>
1306 * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code>
1307 * </ul>
1308 * </p>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001309 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001310 * Beware of the above example. This call is needed only to account for a
1311 * rotation from its natural orientation when calculating the rotation
1312 * angles (see {@link #getOrientation}). If the rotation matrix is also used
1313 * for rendering, it may not need to be transformed, for instance if your
1314 * {@link android.app.Activity Activity} is running in landscape mode.
1315 * </ul>
Mathias Agopian0f791a72010-06-22 21:55:01 -07001316 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001317 * <p>
1318 * Since the resulting coordinate system is orthonormal, only two axes need
1319 * to be specified.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001320 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001321 * @param inR
1322 * the rotation matrix to be transformed. Usually it is the matrix
1323 * returned by {@link #getRotationMatrix}.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001324 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001325 * @param X
Peng Xuca09d8c2015-05-21 18:06:06 -07001326 * defines the axis of the new cooridinate system that coincide with the X axis of the
1327 * original coordinate system.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001328 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001329 * @param Y
Peng Xuca09d8c2015-05-21 18:06:06 -07001330 * defines the axis of the new cooridinate system that coincide with the Y axis of the
1331 * original coordinate system.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001332 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001333 * @param outR
Katie McCormickf2ef28d2013-11-26 11:10:54 -08001334 * the transformed rotation matrix. inR and outR should not be the same
1335 * array.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001336 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001337 * @return <code>true</code> on success. <code>false</code> if the input
1338 * parameters are incorrect, for instance if X and Y define the same
1339 * axis. Or if inR and outR don't have the same length.
Mathias Agopian0f791a72010-06-22 21:55:01 -07001340 *
1341 * @see #getRotationMatrix(float[], float[], float[], float[])
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 */
1343
Peng Xu62f2c872017-09-22 11:50:33 -07001344 public static boolean remapCoordinateSystem(float[] inR, int X, int Y, float[] outR) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001345 if (inR == outR) {
Peng Xu62f2c872017-09-22 11:50:33 -07001346 final float[] temp = sTempMatrix;
1347 synchronized (temp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 // we don't expect to have a lot of contention
1349 if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
1350 final int size = outR.length;
Peng Xu62f2c872017-09-22 11:50:33 -07001351 for (int i = 0; i < size; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 outR[i] = temp[i];
Peng Xu62f2c872017-09-22 11:50:33 -07001353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001354 return true;
1355 }
1356 }
1357 }
1358 return remapCoordinateSystemImpl(inR, X, Y, outR);
1359 }
1360
Peng Xu62f2c872017-09-22 11:50:33 -07001361 private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y, float[] outR) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362 /*
1363 * X and Y define a rotation matrix 'r':
1364 *
1365 * (X==1)?((X&0x80)?-1:1):0 (X==2)?((X&0x80)?-1:1):0 (X==3)?((X&0x80)?-1:1):0
1366 * (Y==1)?((Y&0x80)?-1:1):0 (Y==2)?((Y&0x80)?-1:1):0 (Y==3)?((X&0x80)?-1:1):0
1367 * r[0] ^ r[1]
1368 *
1369 * where the 3rd line is the vector product of the first 2 lines
1370 *
1371 */
1372
1373 final int length = outR.length;
Peng Xu62f2c872017-09-22 11:50:33 -07001374 if (inR.length != length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 return false; // invalid parameter
Peng Xu62f2c872017-09-22 11:50:33 -07001376 }
1377 if ((X & 0x7C) != 0 || (Y & 0x7C) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 return false; // invalid parameter
Peng Xu62f2c872017-09-22 11:50:33 -07001379 }
1380 if (((X & 0x3) == 0) || ((Y & 0x3) == 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 return false; // no axis specified
Peng Xu62f2c872017-09-22 11:50:33 -07001382 }
1383 if ((X & 0x3) == (Y & 0x3)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 return false; // same axis specified
Peng Xu62f2c872017-09-22 11:50:33 -07001385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001386
1387 // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
1388 // this can be calculated by exclusive-or'ing X and Y; except for
1389 // the sign inversion (+/-) which is calculated below.
1390 int Z = X ^ Y;
1391
1392 // extract the axis (remove the sign), offset in the range 0 to 2.
Peng Xu62f2c872017-09-22 11:50:33 -07001393 final int x = (X & 0x3) - 1;
1394 final int y = (Y & 0x3) - 1;
1395 final int z = (Z & 0x3) - 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396
1397 // compute the sign of Z (whether it needs to be inverted)
Peng Xu62f2c872017-09-22 11:50:33 -07001398 final int axis_y = (z + 1) % 3;
1399 final int axis_z = (z + 2) % 3;
1400 if (((x ^ axis_y) | (y ^ axis_z)) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401 Z ^= 0x80;
Peng Xu62f2c872017-09-22 11:50:33 -07001402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403
Peng Xu62f2c872017-09-22 11:50:33 -07001404 final boolean sx = (X >= 0x80);
1405 final boolean sy = (Y >= 0x80);
1406 final boolean sz = (Z >= 0x80);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407
1408 // Perform R * r, in avoiding actual muls and adds.
Peng Xu62f2c872017-09-22 11:50:33 -07001409 final int rowLength = ((length == 16) ? 4 : 3);
1410 for (int j = 0; j < 3; j++) {
1411 final int offset = j * rowLength;
1412 for (int i = 0; i < 3; i++) {
1413 if (x == i) outR[offset + i] = sx ? -inR[offset + 0] : inR[offset + 0];
1414 if (y == i) outR[offset + i] = sy ? -inR[offset + 1] : inR[offset + 1];
1415 if (z == i) outR[offset + i] = sz ? -inR[offset + 2] : inR[offset + 2];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001416 }
1417 }
1418 if (length == 16) {
1419 outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
1420 outR[15] = 1;
1421 }
1422 return true;
1423 }
1424
1425 /**
1426 * Computes the device's orientation based on the rotation matrix.
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001427 * <p>
Kevin Hufnagleb4839de2016-04-25 13:33:53 -07001428 * When it returns, the array values are as follows:
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001429 * <ul>
Kevin Hufnagleb4839de2016-04-25 13:33:53 -07001430 * <li>values[0]: <i>Azimuth</i>, angle of rotation about the -z axis.
1431 * This value represents the angle between the device's y
1432 * axis and the magnetic north pole. When facing north, this
1433 * angle is 0, when facing south, this angle is &pi;.
1434 * Likewise, when facing east, this angle is &pi;/2, and
1435 * when facing west, this angle is -&pi;/2. The range of
1436 * values is -&pi; to &pi;.</li>
1437 * <li>values[1]: <i>Pitch</i>, angle of rotation about the x axis.
1438 * This value represents the angle between a plane parallel
1439 * to the device's screen and a plane parallel to the ground.
1440 * Assuming that the bottom edge of the device faces the
1441 * user and that the screen is face-up, tilting the top edge
1442 * of the device toward the ground creates a positive pitch
1443 * angle. The range of values is -&pi; to &pi;.</li>
1444 * <li>values[2]: <i>Roll</i>, angle of rotation about the y axis. This
1445 * value represents the angle between a plane perpendicular
1446 * to the device's screen and a plane perpendicular to the
1447 * ground. Assuming that the bottom edge of the device faces
1448 * the user and that the screen is face-up, tilting the left
1449 * edge of the device toward the ground creates a positive
1450 * roll angle. The range of values is -&pi;/2 to &pi;/2.</li>
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001451 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 * <p>
Kevin Hufnagleb4839de2016-04-25 13:33:53 -07001453 * Applying these three rotations in the azimuth, pitch, roll order
1454 * transforms an identity matrix to the rotation matrix passed into this
1455 * method. Also, note that all three orientation angles are expressed in
1456 * <b>radians</b>.
Aravind Akellab4c76b12013-06-27 12:04:16 -07001457 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001458 * @param R
1459 * rotation matrix see {@link #getRotationMatrix}.
Aravind Akellab4c76b12013-06-27 12:04:16 -07001460 *
Mathias Agopian74cde2c2010-06-16 18:55:46 -07001461 * @param values
1462 * an array of 3 floats to hold the result.
Aravind Akellab4c76b12013-06-27 12:04:16 -07001463 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 * @return The array values passed as argument.
Aravind Akellab4c76b12013-06-27 12:04:16 -07001465 *
Mathias Agopian0f791a72010-06-22 21:55:01 -07001466 * @see #getRotationMatrix(float[], float[], float[], float[])
1467 * @see GeomagneticField
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001468 */
Peng Xu62f2c872017-09-22 11:50:33 -07001469 public static float[] getOrientation(float[] R, float[] values) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 /*
1471 * 4x4 (length=16) case:
1472 * / R[ 0] R[ 1] R[ 2] 0 \
1473 * | R[ 4] R[ 5] R[ 6] 0 |
1474 * | R[ 8] R[ 9] R[10] 0 |
1475 * \ 0 0 0 1 /
Mathias Agopian0f791a72010-06-22 21:55:01 -07001476 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 * 3x3 (length=9) case:
1478 * / R[ 0] R[ 1] R[ 2] \
1479 * | R[ 3] R[ 4] R[ 5] |
1480 * \ R[ 6] R[ 7] R[ 8] /
Mathias Agopian0f791a72010-06-22 21:55:01 -07001481 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482 */
1483 if (R.length == 9) {
Peng Xu62f2c872017-09-22 11:50:33 -07001484 values[0] = (float) Math.atan2(R[1], R[4]);
1485 values[1] = (float) Math.asin(-R[7]);
1486 values[2] = (float) Math.atan2(-R[6], R[8]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 } else {
Peng Xu62f2c872017-09-22 11:50:33 -07001488 values[0] = (float) Math.atan2(R[1], R[5]);
1489 values[1] = (float) Math.asin(-R[9]);
1490 values[2] = (float) Math.atan2(-R[8], R[10]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 }
Peng Xuca09d8c2015-05-21 18:06:06 -07001492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 return values;
1494 }
1495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 /**
Mathias Agopian04d7e83e2010-07-29 17:59:58 -07001497 * Computes the Altitude in meters from the atmospheric pressure and the
1498 * pressure at sea level.
1499 * <p>
1500 * Typically the atmospheric pressure is read from a
1501 * {@link Sensor#TYPE_PRESSURE} sensor. The pressure at sea level must be
1502 * known, usually it can be retrieved from airport databases in the
Mathias Agopiana6704d32010-08-18 12:00:30 -07001503 * vicinity. If unknown, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE}
1504 * as an approximation, but absolute altitudes won't be accurate.
1505 * </p>
1506 * <p>
1507 * To calculate altitude differences, you must calculate the difference
1508 * between the altitudes at both points. If you don't know the altitude
1509 * as sea level, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE} instead,
1510 * which will give good results considering the range of pressure typically
1511 * involved.
1512 * </p>
1513 * <p>
1514 * <code><ul>
1515 * float altitude_difference =
1516 * getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point2)
1517 * - getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point1);
1518 * </ul></code>
Mathias Agopian04d7e83e2010-07-29 17:59:58 -07001519 * </p>
1520 *
1521 * @param p0 pressure at sea level
1522 * @param p atmospheric pressure
1523 * @return Altitude in meters
1524 */
Jeff Brown25157e42012-04-16 12:13:05 -07001525 public static float getAltitude(float p0, float p) {
Mathias Agopian04d7e83e2010-07-29 17:59:58 -07001526 final float coef = 1.0f / 5.255f;
Peng Xu62f2c872017-09-22 11:50:33 -07001527 return 44330.0f * (1.0f - (float) Math.pow(p / p0, coef));
Mathias Agopian04d7e83e2010-07-29 17:59:58 -07001528 }
1529
Kevin Powell7a0541d2010-07-19 19:10:40 -07001530 /** Helper function to compute the angle change between two rotation matrices.
1531 * Given a current rotation matrix (R) and a previous rotation matrix
Peng Xuca09d8c2015-05-21 18:06:06 -07001532 * (prevR) computes the intrinsic rotation around the z, x, and y axes which
Kevin Powell7a0541d2010-07-19 19:10:40 -07001533 * transforms prevR to R.
Peng Xuca09d8c2015-05-21 18:06:06 -07001534 * outputs a 3 element vector containing the z, x, and y angle
Kevin Powell7a0541d2010-07-19 19:10:40 -07001535 * change at indexes 0, 1, and 2 respectively.
1536 * <p> Each input matrix is either as a 3x3 or 4x4 row-major matrix
1537 * depending on the length of the passed array:
1538 * <p>If the array length is 9, then the array elements represent this matrix
1539 * <pre>
1540 * / R[ 0] R[ 1] R[ 2] \
1541 * | R[ 3] R[ 4] R[ 5] |
1542 * \ R[ 6] R[ 7] R[ 8] /
1543 *</pre>
1544 * <p>If the array length is 16, then the array elements represent this matrix
1545 * <pre>
1546 * / R[ 0] R[ 1] R[ 2] R[ 3] \
1547 * | R[ 4] R[ 5] R[ 6] R[ 7] |
1548 * | R[ 8] R[ 9] R[10] R[11] |
1549 * \ R[12] R[13] R[14] R[15] /
1550 *</pre>
Peng Xuca09d8c2015-05-21 18:06:06 -07001551 *
1552 * See {@link #getOrientation} for more detailed definition of the output.
1553 *
Kevin Powell7a0541d2010-07-19 19:10:40 -07001554 * @param R current rotation matrix
1555 * @param prevR previous rotation matrix
Peng Xuca09d8c2015-05-21 18:06:06 -07001556 * @param angleChange an an array of floats (z, x, and y) in which the angle change
1557 * (in radians) is stored
Kevin Powell7a0541d2010-07-19 19:10:40 -07001558 */
1559
Peng Xu62f2c872017-09-22 11:50:33 -07001560 public static void getAngleChange(float[] angleChange, float[] R, float[] prevR) {
1561 float rd1 = 0, rd4 = 0, rd6 = 0, rd7 = 0, rd8 = 0;
1562 float ri0 = 0, ri1 = 0, ri2 = 0, ri3 = 0, ri4 = 0, ri5 = 0, ri6 = 0, ri7 = 0, ri8 = 0;
1563 float pri0 = 0, pri1 = 0, pri2 = 0, pri3 = 0, pri4 = 0;
1564 float pri5 = 0, pri6 = 0, pri7 = 0, pri8 = 0;
Kevin Powell7a0541d2010-07-19 19:10:40 -07001565
Peng Xu62f2c872017-09-22 11:50:33 -07001566 if (R.length == 9) {
Kevin Powell7a0541d2010-07-19 19:10:40 -07001567 ri0 = R[0];
1568 ri1 = R[1];
1569 ri2 = R[2];
1570 ri3 = R[3];
1571 ri4 = R[4];
1572 ri5 = R[5];
1573 ri6 = R[6];
1574 ri7 = R[7];
1575 ri8 = R[8];
Peng Xu62f2c872017-09-22 11:50:33 -07001576 } else if (R.length == 16) {
Kevin Powell7a0541d2010-07-19 19:10:40 -07001577 ri0 = R[0];
1578 ri1 = R[1];
1579 ri2 = R[2];
1580 ri3 = R[4];
1581 ri4 = R[5];
1582 ri5 = R[6];
1583 ri6 = R[8];
1584 ri7 = R[9];
1585 ri8 = R[10];
1586 }
1587
Peng Xu62f2c872017-09-22 11:50:33 -07001588 if (prevR.length == 9) {
Kevin Powell34884b42010-11-03 16:04:30 -07001589 pri0 = prevR[0];
1590 pri1 = prevR[1];
1591 pri2 = prevR[2];
1592 pri3 = prevR[3];
1593 pri4 = prevR[4];
1594 pri5 = prevR[5];
1595 pri6 = prevR[6];
1596 pri7 = prevR[7];
1597 pri8 = prevR[8];
Peng Xu62f2c872017-09-22 11:50:33 -07001598 } else if (prevR.length == 16) {
Kevin Powell34884b42010-11-03 16:04:30 -07001599 pri0 = prevR[0];
1600 pri1 = prevR[1];
1601 pri2 = prevR[2];
1602 pri3 = prevR[4];
1603 pri4 = prevR[5];
1604 pri5 = prevR[6];
1605 pri6 = prevR[8];
1606 pri7 = prevR[9];
1607 pri8 = prevR[10];
Kevin Powell7a0541d2010-07-19 19:10:40 -07001608 }
1609
1610 // calculate the parts of the rotation difference matrix we need
1611 // rd[i][j] = pri[0][i] * ri[0][j] + pri[1][i] * ri[1][j] + pri[2][i] * ri[2][j];
1612
1613 rd1 = pri0 * ri1 + pri3 * ri4 + pri6 * ri7; //rd[0][1]
1614 rd4 = pri1 * ri1 + pri4 * ri4 + pri7 * ri7; //rd[1][1]
1615 rd6 = pri2 * ri0 + pri5 * ri3 + pri8 * ri6; //rd[2][0]
1616 rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1]
1617 rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2]
1618
Peng Xu62f2c872017-09-22 11:50:33 -07001619 angleChange[0] = (float) Math.atan2(rd1, rd4);
1620 angleChange[1] = (float) Math.asin(-rd7);
1621 angleChange[2] = (float) Math.atan2(-rd6, rd8);
Kevin Powell7a0541d2010-07-19 19:10:40 -07001622
1623 }
1624
1625 /** Helper function to convert a rotation vector to a rotation matrix.
1626 * Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a
1627 * 9 or 16 element rotation matrix in the array R. R must have length 9 or 16.
1628 * If R.length == 9, the following matrix is returned:
1629 * <pre>
1630 * / R[ 0] R[ 1] R[ 2] \
1631 * | R[ 3] R[ 4] R[ 5] |
1632 * \ R[ 6] R[ 7] R[ 8] /
1633 *</pre>
1634 * If R.length == 16, the following matrix is returned:
1635 * <pre>
1636 * / R[ 0] R[ 1] R[ 2] 0 \
1637 * | R[ 4] R[ 5] R[ 6] 0 |
1638 * | R[ 8] R[ 9] R[10] 0 |
1639 * \ 0 0 0 1 /
1640 *</pre>
1641 * @param rotationVector the rotation vector to convert
1642 * @param R an array of floats in which to store the rotation matrix
1643 */
1644 public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) {
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001645
1646 float q0;
Kevin Powell7a0541d2010-07-19 19:10:40 -07001647 float q1 = rotationVector[0];
1648 float q2 = rotationVector[1];
1649 float q3 = rotationVector[2];
1650
Balint Ureczky12d39b92013-12-05 00:03:45 +01001651 if (rotationVector.length >= 4) {
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001652 q0 = rotationVector[3];
1653 } else {
Peng Xu62f2c872017-09-22 11:50:33 -07001654 q0 = 1 - q1 * q1 - q2 * q2 - q3 * q3;
1655 q0 = (q0 > 0) ? (float) Math.sqrt(q0) : 0;
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001656 }
1657
Kevin Powell7a0541d2010-07-19 19:10:40 -07001658 float sq_q1 = 2 * q1 * q1;
1659 float sq_q2 = 2 * q2 * q2;
1660 float sq_q3 = 2 * q3 * q3;
1661 float q1_q2 = 2 * q1 * q2;
1662 float q3_q0 = 2 * q3 * q0;
1663 float q1_q3 = 2 * q1 * q3;
1664 float q2_q0 = 2 * q2 * q0;
1665 float q2_q3 = 2 * q2 * q3;
1666 float q1_q0 = 2 * q1 * q0;
1667
Peng Xu62f2c872017-09-22 11:50:33 -07001668 if (R.length == 9) {
Kevin Powell7a0541d2010-07-19 19:10:40 -07001669 R[0] = 1 - sq_q2 - sq_q3;
1670 R[1] = q1_q2 - q3_q0;
1671 R[2] = q1_q3 + q2_q0;
1672
1673 R[3] = q1_q2 + q3_q0;
1674 R[4] = 1 - sq_q1 - sq_q3;
1675 R[5] = q2_q3 - q1_q0;
1676
1677 R[6] = q1_q3 - q2_q0;
1678 R[7] = q2_q3 + q1_q0;
1679 R[8] = 1 - sq_q1 - sq_q2;
1680 } else if (R.length == 16) {
1681 R[0] = 1 - sq_q2 - sq_q3;
1682 R[1] = q1_q2 - q3_q0;
1683 R[2] = q1_q3 + q2_q0;
1684 R[3] = 0.0f;
1685
1686 R[4] = q1_q2 + q3_q0;
1687 R[5] = 1 - sq_q1 - sq_q3;
1688 R[6] = q2_q3 - q1_q0;
1689 R[7] = 0.0f;
1690
1691 R[8] = q1_q3 - q2_q0;
1692 R[9] = q2_q3 + q1_q0;
1693 R[10] = 1 - sq_q1 - sq_q2;
1694 R[11] = 0.0f;
1695
1696 R[12] = R[13] = R[14] = 0.0f;
1697 R[15] = 1.0f;
1698 }
1699 }
1700
1701 /** Helper function to convert a rotation vector to a normalized quaternion.
1702 * Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a normalized
1703 * quaternion in the array Q. The quaternion is stored as [w, x, y, z]
1704 * @param rv the rotation vector to convert
1705 * @param Q an array of floats in which to store the computed quaternion
1706 */
1707 public static void getQuaternionFromVector(float[] Q, float[] rv) {
Balint Ureczky12d39b92013-12-05 00:03:45 +01001708 if (rv.length >= 4) {
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001709 Q[0] = rv[3];
1710 } else {
Peng Xu62f2c872017-09-22 11:50:33 -07001711 Q[0] = 1 - rv[0] * rv[0] - rv[1] * rv[1] - rv[2] * rv[2];
1712 Q[0] = (Q[0] > 0) ? (float) Math.sqrt(Q[0]) : 0;
Mathias Agopian7badd2c2010-11-22 15:48:10 -08001713 }
Kevin Powell7a0541d2010-07-19 19:10:40 -07001714 Q[1] = rv[0];
1715 Q[2] = rv[1];
1716 Q[3] = rv[2];
1717 }
1718
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -08001719 /**
1720 * Requests receiving trigger events for a trigger sensor.
1721 *
1722 * <p>
1723 * When the sensor detects a trigger event condition, such as significant motion in
1724 * the case of the {@link Sensor#TYPE_SIGNIFICANT_MOTION}, the provided trigger listener
1725 * will be invoked once and then its request to receive trigger events will be canceled.
1726 * To continue receiving trigger events, the application must request to receive trigger
1727 * events again.
1728 * </p>
1729 *
1730 * @param listener The listener on which the
1731 * {@link TriggerEventListener#onTrigger(TriggerEvent)} will be delivered.
1732 * @param sensor The sensor to be enabled.
1733 *
1734 * @return true if the sensor was successfully enabled.
1735 *
1736 * @throws IllegalArgumentException when sensor is null or not a trigger sensor.
1737 */
1738 public boolean requestTriggerSensor(TriggerEventListener listener, Sensor sensor) {
1739 return requestTriggerSensorImpl(listener, sensor);
1740 }
1741
1742 /**
1743 * @hide
1744 */
1745 protected abstract boolean requestTriggerSensorImpl(TriggerEventListener listener,
1746 Sensor sensor);
1747
1748 /**
1749 * Cancels receiving trigger events for a trigger sensor.
1750 *
1751 * <p>
1752 * Note that a Trigger sensor will be auto disabled if
1753 * {@link TriggerEventListener#onTrigger(TriggerEvent)} has triggered.
1754 * This method is provided in case the user wants to explicitly cancel the request
1755 * to receive trigger events.
1756 * </p>
1757 *
1758 * @param listener The listener on which the
1759 * {@link TriggerEventListener#onTrigger(TriggerEvent)}
1760 * is delivered.It should be the same as the one used
1761 * in {@link #requestTriggerSensor(TriggerEventListener, Sensor)}
1762 * @param sensor The sensor for which the trigger request should be canceled.
1763 * If null, it cancels receiving trigger for all sensors associated
1764 * with the listener.
1765 *
1766 * @return true if successfully canceled.
1767 *
1768 * @throws IllegalArgumentException when sensor is a trigger sensor.
1769 */
1770 public boolean cancelTriggerSensor(TriggerEventListener listener, Sensor sensor) {
Jaikumar Ganesh2e900892013-04-11 10:40:33 -07001771 return cancelTriggerSensorImpl(listener, sensor, true);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -08001772 }
1773
1774 /**
1775 * @hide
1776 */
1777 protected abstract boolean cancelTriggerSensorImpl(TriggerEventListener listener,
Jaikumar Ganesh2e900892013-04-11 10:40:33 -07001778 Sensor sensor, boolean disable);
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -08001779
1780
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001781 /**
1782 * For testing purposes only. Not for third party applications.
1783 *
Aravind Akellad123b512015-06-29 12:35:51 -07001784 * Initialize data injection mode and create a client for data injection. SensorService should
1785 * already be operating in DATA_INJECTION mode for this call succeed. To set SensorService into
1786 * DATA_INJECTION mode "adb shell dumpsys sensorservice data_injection" needs to be called
1787 * through adb. Typically this is done using a host side test. This mode is expected to be used
1788 * only for testing purposes. If the HAL is set to data injection mode, it will ignore the input
1789 * from physical sensors and read sensor data that is injected from the test application. This
1790 * mode is used for testing vendor implementations for various algorithms like Rotation Vector,
1791 * Significant Motion, Step Counter etc. Not all HALs support DATA_INJECTION. This method will
1792 * fail in those cases. Once this method succeeds, the test can call
1793 * {@link injectSensorData(Sensor, float[], int, long)} to inject sensor data into the HAL.
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001794 *
Aravind Akellad123b512015-06-29 12:35:51 -07001795 * @param enable True to initialize a client in DATA_INJECTION mode.
1796 * False to clean up the native resources.
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001797 *
1798 * @return true if the HAL supports data injection and false
1799 * otherwise.
1800 * @hide
1801 */
1802 @SystemApi
Aravind Akellad123b512015-06-29 12:35:51 -07001803 public boolean initDataInjection(boolean enable) {
Peng Xu62f2c872017-09-22 11:50:33 -07001804 return initDataInjectionImpl(enable);
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001805 }
1806
1807 /**
1808 * @hide
1809 */
Aravind Akellad123b512015-06-29 12:35:51 -07001810 protected abstract boolean initDataInjectionImpl(boolean enable);
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001811
1812 /**
1813 * For testing purposes only. Not for third party applications.
1814 *
Aravind Akellad123b512015-06-29 12:35:51 -07001815 * This method is used to inject raw sensor data into the HAL. Call {@link
1816 * initDataInjection(boolean)} before this method to set the HAL in data injection mode. This
1817 * method should be called only if a previous call to initDataInjection has been successful and
1818 * the HAL and SensorService are already opreating in data injection mode.
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001819 *
1820 * @param sensor The sensor to inject.
1821 * @param values Sensor values to inject. The length of this
1822 * array must be exactly equal to the number of
1823 * values reported by the sensor type.
1824 * @param accuracy Accuracy of the sensor.
1825 * @param timestamp Sensor timestamp associated with the event.
1826 *
1827 * @return boolean True if the data injection succeeds, false
1828 * otherwise.
1829 * @throws IllegalArgumentException when the sensor is null,
1830 * data injection is not supported by the sensor, values
1831 * are null, incorrect number of values for the sensor,
1832 * sensor accuracy is incorrect or timestamps are
1833 * invalid.
1834 * @hide
1835 */
1836 @SystemApi
1837 public boolean injectSensorData(Sensor sensor, float[] values, int accuracy,
1838 long timestamp) {
1839 if (sensor == null) {
1840 throw new IllegalArgumentException("sensor cannot be null");
1841 }
1842 if (!sensor.isDataInjectionSupported()) {
1843 throw new IllegalArgumentException("sensor does not support data injection");
1844 }
1845 if (values == null) {
1846 throw new IllegalArgumentException("sensor data cannot be null");
1847 }
Dianne Hackborn0e3de6c2015-07-29 15:20:21 -07001848 int expectedNumValues = Sensor.getMaxLengthValuesArray(sensor, Build.VERSION_CODES.M);
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001849 if (values.length != expectedNumValues) {
Peng Xu62f2c872017-09-22 11:50:33 -07001850 throw new IllegalArgumentException("Wrong number of values for sensor "
1851 + sensor.getName() + " actual=" + values.length + " expected="
1852 + expectedNumValues);
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001853 }
1854 if (accuracy < SENSOR_STATUS_NO_CONTACT || accuracy > SENSOR_STATUS_ACCURACY_HIGH) {
1855 throw new IllegalArgumentException("Invalid sensor accuracy");
1856 }
1857 if (timestamp <= 0) {
1858 throw new IllegalArgumentException("Negative or zero sensor timestamp");
1859 }
Aravind Akella18ebf732b2015-04-20 17:39:51 -07001860 return injectSensorDataImpl(sensor, values, accuracy, timestamp);
1861 }
1862
1863 /**
1864 * @hide
1865 */
1866 protected abstract boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
1867 long timestamp);
1868
Jeff Brown4481d9c2012-04-16 16:14:44 -07001869 private LegacySensorManager getLegacySensorManager() {
1870 synchronized (mSensorListByType) {
1871 if (mLegacySensorManager == null) {
1872 Log.i(TAG, "This application is using deprecated SensorManager API which will "
1873 + "be removed someday. Please consider switching to the new API.");
1874 mLegacySensorManager = new LegacySensorManager(this);
Jeff Brown25157e42012-04-16 12:13:05 -07001875 }
Jeff Brown4481d9c2012-04-16 16:14:44 -07001876 return mLegacySensorManager;
Jeff Brown25157e42012-04-16 12:13:05 -07001877 }
1878 }
Aravind Akellab4c76b12013-06-27 12:04:16 -07001879
1880 private static int getDelay(int rate) {
1881 int delay = -1;
1882 switch (rate) {
1883 case SENSOR_DELAY_FASTEST:
1884 delay = 0;
1885 break;
1886 case SENSOR_DELAY_GAME:
1887 delay = 20000;
1888 break;
1889 case SENSOR_DELAY_UI:
1890 delay = 66667;
1891 break;
1892 case SENSOR_DELAY_NORMAL:
1893 delay = 200000;
1894 break;
1895 default:
1896 delay = rate;
1897 break;
1898 }
1899 return delay;
1900 }
Peng Xu1cfde252017-01-19 17:10:09 -08001901
1902 /** @hide */
1903 public boolean setOperationParameter(SensorAdditionalInfo parameter) {
1904 return setOperationParameterImpl(parameter);
1905 }
1906
1907 /** @hide */
1908 protected abstract boolean setOperationParameterImpl(SensorAdditionalInfo parameter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001909}