1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.hardware; 18 19 import android.annotation.SystemApi; 20 import android.annotation.SystemService; 21 import android.compat.annotation.UnsupportedAppUsage; 22 import android.content.Context; 23 import android.os.Build; 24 import android.os.Handler; 25 import android.os.MemoryFile; 26 import android.util.Log; 27 import android.util.SparseArray; 28 29 import java.util.ArrayList; 30 import java.util.Collections; 31 import java.util.List; 32 33 /** 34 * <p> 35 * SensorManager lets you access the device's {@link android.hardware.Sensor 36 * sensors}. 37 * </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> 44 * <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> 49 * <pre class="prettyprint"> 50 * public class SensorActivity extends Activity implements SensorEventListener { 51 * 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); 57 * } 58 * 59 * protected void onResume() { 60 * super.onResume(); 61 * mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); 62 * } 63 * 64 * protected void onPause() { 65 * super.onPause(); 66 * mSensorManager.unregisterListener(this); 67 * } 68 * 69 * public void onAccuracyChanged(Sensor sensor, int accuracy) { 70 * } 71 * 72 * public void onSensorChanged(SensorEvent event) { 73 * } 74 * } 75 * </pre> 76 * 77 * @see SensorEventListener 78 * @see SensorEvent 79 * @see Sensor 80 * 81 */ 82 @SystemService(Context.SENSOR_SERVICE) 83 public abstract class SensorManager { 84 /** @hide */ 85 protected static final String TAG = "SensorManager"; 86 87 private static final float[] sTempMatrix = new float[16]; 88 89 // Cached lists of sensors by type. Guarded by mSensorListByType. 90 private final SparseArray<List<Sensor>> mSensorListByType = 91 new SparseArray<List<Sensor>>(); 92 93 // Legacy sensor manager implementation. Guarded by mSensorListByType during initialization. 94 private LegacySensorManager mLegacySensorManager; 95 96 /* NOTE: sensor IDs must be a power of 2 */ 97 98 /** 99 * A constant describing an orientation sensor. See 100 * {@link android.hardware.SensorListener SensorListener} for more details. 101 * 102 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 103 */ 104 @Deprecated 105 public static final int SENSOR_ORIENTATION = 1 << 0; 106 107 /** 108 * A constant describing an accelerometer. See 109 * {@link android.hardware.SensorListener SensorListener} for more details. 110 * 111 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 112 */ 113 @Deprecated 114 public static final int SENSOR_ACCELEROMETER = 1 << 1; 115 116 /** 117 * A constant describing a temperature sensor See 118 * {@link android.hardware.SensorListener SensorListener} for more details. 119 * 120 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 121 */ 122 @Deprecated 123 public static final int SENSOR_TEMPERATURE = 1 << 2; 124 125 /** 126 * A constant describing a magnetic sensor See 127 * {@link android.hardware.SensorListener SensorListener} for more details. 128 * 129 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 130 */ 131 @Deprecated 132 public static final int SENSOR_MAGNETIC_FIELD = 1 << 3; 133 134 /** 135 * A constant describing an ambient light sensor See 136 * {@link android.hardware.SensorListener SensorListener} for more details. 137 * 138 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 139 */ 140 @Deprecated 141 public static final int SENSOR_LIGHT = 1 << 4; 142 143 /** 144 * A constant describing a proximity sensor See 145 * {@link android.hardware.SensorListener SensorListener} for more details. 146 * 147 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 148 */ 149 @Deprecated 150 public static final int SENSOR_PROXIMITY = 1 << 5; 151 152 /** 153 * A constant describing a Tricorder See 154 * {@link android.hardware.SensorListener SensorListener} for more details. 155 * 156 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 157 */ 158 @Deprecated 159 public static final int SENSOR_TRICORDER = 1 << 6; 160 161 /** 162 * A constant describing an orientation sensor. See 163 * {@link android.hardware.SensorListener SensorListener} for more details. 164 * 165 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 166 */ 167 @Deprecated 168 public static final int SENSOR_ORIENTATION_RAW = 1 << 7; 169 170 /** 171 * A constant that includes all sensors 172 * 173 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 174 */ 175 @Deprecated 176 public static final int SENSOR_ALL = 0x7F; 177 178 /** 179 * Smallest sensor ID 180 * 181 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 182 */ 183 @Deprecated 184 public static final int SENSOR_MIN = SENSOR_ORIENTATION; 185 186 /** 187 * Largest sensor ID 188 * 189 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 190 */ 191 @Deprecated 192 public static final int SENSOR_MAX = ((SENSOR_ALL + 1) >> 1); 193 194 195 /** 196 * Index of the X value in the array returned by 197 * {@link android.hardware.SensorListener#onSensorChanged} 198 * 199 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 200 */ 201 @Deprecated 202 public static final int DATA_X = 0; 203 204 /** 205 * Index of the Y value in the array returned by 206 * {@link android.hardware.SensorListener#onSensorChanged} 207 * 208 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 209 */ 210 @Deprecated 211 public static final int DATA_Y = 1; 212 213 /** 214 * Index of the Z value in the array returned by 215 * {@link android.hardware.SensorListener#onSensorChanged} 216 * 217 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 218 */ 219 @Deprecated 220 public static final int DATA_Z = 2; 221 222 /** 223 * Offset to the untransformed values in the array returned by 224 * {@link android.hardware.SensorListener#onSensorChanged} 225 * 226 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 227 */ 228 @Deprecated 229 public static final int RAW_DATA_INDEX = 3; 230 231 /** 232 * Index of the untransformed X value in the array returned by 233 * {@link android.hardware.SensorListener#onSensorChanged} 234 * 235 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 236 */ 237 @Deprecated 238 public static final int RAW_DATA_X = 3; 239 240 /** 241 * Index of the untransformed Y value in the array returned by 242 * {@link android.hardware.SensorListener#onSensorChanged} 243 * 244 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 245 */ 246 @Deprecated 247 public static final int RAW_DATA_Y = 4; 248 249 /** 250 * Index of the untransformed Z value in the array returned by 251 * {@link android.hardware.SensorListener#onSensorChanged} 252 * 253 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 254 */ 255 @Deprecated 256 public static final int RAW_DATA_Z = 5; 257 258 /** Standard gravity (g) on Earth. This value is equivalent to 1G */ 259 public static final float STANDARD_GRAVITY = 9.80665f; 260 261 /** Sun's gravity in SI units (m/s^2) */ 262 public static final float GRAVITY_SUN = 275.0f; 263 /** Mercury's gravity in SI units (m/s^2) */ 264 public static final float GRAVITY_MERCURY = 3.70f; 265 /** Venus' gravity in SI units (m/s^2) */ 266 public static final float GRAVITY_VENUS = 8.87f; 267 /** Earth's gravity in SI units (m/s^2) */ 268 public static final float GRAVITY_EARTH = 9.80665f; 269 /** The Moon's gravity in SI units (m/s^2) */ 270 public static final float GRAVITY_MOON = 1.6f; 271 /** Mars' gravity in SI units (m/s^2) */ 272 public static final float GRAVITY_MARS = 3.71f; 273 /** Jupiter's gravity in SI units (m/s^2) */ 274 public static final float GRAVITY_JUPITER = 23.12f; 275 /** Saturn's gravity in SI units (m/s^2) */ 276 public static final float GRAVITY_SATURN = 8.96f; 277 /** Uranus' gravity in SI units (m/s^2) */ 278 public static final float GRAVITY_URANUS = 8.69f; 279 /** Neptune's gravity in SI units (m/s^2) */ 280 public static final float GRAVITY_NEPTUNE = 11.0f; 281 /** Pluto's gravity in SI units (m/s^2) */ 282 public static final float GRAVITY_PLUTO = 0.6f; 283 /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */ 284 public static final float GRAVITY_DEATH_STAR_I = 0.000000353036145f; 285 /** Gravity on the island */ 286 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; 291 /** Minimum magnetic field on Earth's surface */ 292 public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f; 293 294 295 /** Standard atmosphere, or average sea-level pressure in hPa (millibar) */ 296 public static final float PRESSURE_STANDARD_ATMOSPHERE = 1013.25f; 297 298 299 /** Maximum luminance of sunlight in lux */ 300 public static final float LIGHT_SUNLIGHT_MAX = 120000.0f; 301 /** luminance of sunlight in lux */ 302 public static final float LIGHT_SUNLIGHT = 110000.0f; 303 /** luminance in shade in lux */ 304 public static final float LIGHT_SHADE = 20000.0f; 305 /** luminance under an overcast sky in lux */ 306 public static final float LIGHT_OVERCAST = 10000.0f; 307 /** luminance at sunrise in lux */ 308 public static final float LIGHT_SUNRISE = 400.0f; 309 /** luminance under a cloudy sky in lux */ 310 public static final float LIGHT_CLOUDY = 100.0f; 311 /** luminance at night with full moon in lux */ 312 public static final float LIGHT_FULLMOON = 0.25f; 313 /** luminance at night with no moon in lux*/ 314 public static final float LIGHT_NO_MOON = 0.001f; 315 316 317 /** 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 327 /** 328 * 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 /** 335 * The values returned by this sensor cannot be trusted, calibration is 336 * needed or the environment doesn't allow readings 337 */ 338 public static final int SENSOR_STATUS_UNRELIABLE = 0; 339 340 /** 341 * This sensor is reporting data with low accuracy, calibration with the 342 * environment is needed 343 */ 344 public static final int SENSOR_STATUS_ACCURACY_LOW = 1; 345 346 /** 347 * This sensor is reporting data with an average level of accuracy, 348 * calibration with the environment may improve the readings 349 */ 350 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 368 369 /** 370 * {@hide} 371 */ 372 @UnsupportedAppUsage SensorManager()373 public SensorManager() { 374 } 375 376 /** 377 * Gets the full list of sensors that are available. 378 * @hide 379 */ getFullSensorList()380 protected abstract List<Sensor> getFullSensorList(); 381 382 /** 383 * Gets the full list of dynamic sensors that are available. 384 * @hide 385 */ getFullDynamicSensorList()386 protected abstract List<Sensor> getFullDynamicSensorList(); 387 388 /** 389 * @return available sensors. 390 * @deprecated This method is deprecated, use 391 * {@link SensorManager#getSensorList(int)} instead 392 */ 393 @Deprecated getSensors()394 public int getSensors() { 395 return getLegacySensorManager().getSensors(); 396 } 397 398 /** 399 * 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. 403 * 404 * <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 * 410 * @param type 411 * of sensors requested 412 * 413 * @return a list of sensors matching the asked type. 414 * 415 * @see #getDefaultSensor(int) 416 * @see Sensor 417 */ getSensorList(int type)418 public List<Sensor> getSensorList(int type) { 419 // cache the returned lists the first time 420 List<Sensor> list; 421 final List<Sensor> fullList = getFullSensorList(); 422 synchronized (mSensorListByType) { 423 list = mSensorListByType.get(type); 424 if (list == null) { 425 if (type == Sensor.TYPE_ALL) { 426 list = fullList; 427 } else { 428 list = new ArrayList<Sensor>(); 429 for (Sensor i : fullList) { 430 if (i.getType() == type) { 431 list.add(i); 432 } 433 } 434 } 435 list = Collections.unmodifiableList(list); 436 mSensorListByType.append(type, list); 437 } 438 } 439 return list; 440 } 441 442 /** 443 * 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 */ getDynamicSensorList(int type)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) { 467 if (i.getType() == type) { 468 list.add(i); 469 } 470 } 471 return Collections.unmodifiableList(list); 472 } 473 } 474 475 /** 476 * 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 478 * averaged or filtered. If you need to access the raw sensors use 479 * {@link SensorManager#getSensorList(int) getSensorList}. 480 * 481 * @param type 482 * of sensors requested 483 * 484 * @return the default sensor matching the requested type if one exists and the application 485 * has the necessary permissions, or null otherwise. 486 * 487 * @see #getSensorList(int) 488 * @see Sensor 489 */ getDefaultSensor(int type)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); 493 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. 497 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 || type == Sensor.TYPE_HINGE_ANGLE) { 502 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> 517 * <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> 523 * </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 */ getDefaultSensor(int type, boolean wakeUp)537 public Sensor getDefaultSensor(int type, boolean wakeUp) { 538 List<Sensor> l = getSensorList(type); 539 for (Sensor sensor : l) { 540 if (sensor.isWakeUpSensor() == wakeUp) { 541 return sensor; 542 } 543 } 544 return null; 545 } 546 547 /** 548 * Registers a listener for given sensors. 549 * 550 * @deprecated This method is deprecated, use 551 * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)} 552 * instead. 553 * 554 * @param listener 555 * sensor listener object 556 * 557 * @param sensors 558 * a bit masks of the sensors to register to 559 * 560 * @return <code>true</code> if the sensor is supported and successfully 561 * enabled 562 */ 563 @Deprecated registerListener(SensorListener listener, int sensors)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. 570 * 571 * @deprecated This method is deprecated, use 572 * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)} 573 * instead. 574 * 575 * @param listener 576 * sensor listener object 577 * 578 * @param sensors 579 * a bit masks of the sensors to register to 580 * 581 * @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}. 587 * 588 * @return <code>true</code> if the sensor is supported and successfully 589 * enabled 590 */ 591 @Deprecated registerListener(SensorListener listener, int sensors, int rate)592 public boolean registerListener(SensorListener listener, int sensors, int rate) { 593 return getLegacySensorManager().registerListener(listener, sensors, rate); 594 } 595 596 /** 597 * Unregisters a listener for all sensors. 598 * 599 * @deprecated This method is deprecated, use 600 * {@link SensorManager#unregisterListener(SensorEventListener)} 601 * instead. 602 * 603 * @param listener 604 * a SensorListener object 605 */ 606 @Deprecated unregisterListener(SensorListener listener)607 public void unregisterListener(SensorListener listener) { 608 unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW); 609 } 610 611 /** 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 unregisterListener(SensorListener listener, int sensors)625 public void unregisterListener(SensorListener listener, int sensors) { 626 getLegacySensorManager().unregisterListener(listener, sensors); 627 } 628 629 /** 630 * Unregisters a listener for the sensors with which it is registered. 631 * 632 * <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 * 638 * @param listener 639 * a SensorEventListener object 640 * 641 * @param sensor 642 * the sensor to unregister from 643 * 644 * @see #unregisterListener(SensorEventListener) 645 * @see #registerListener(SensorEventListener, Sensor, int) 646 */ unregisterListener(SensorEventListener listener, Sensor sensor)647 public void unregisterListener(SensorEventListener listener, Sensor sensor) { 648 if (listener == null || sensor == null) { 649 return; 650 } 651 652 unregisterListenerImpl(listener, sensor); 653 } 654 655 /** 656 * Unregisters a listener for all sensors. 657 * 658 * @param listener 659 * a SensorListener object 660 * 661 * @see #unregisterListener(SensorEventListener, Sensor) 662 * @see #registerListener(SensorEventListener, Sensor, int) 663 * 664 */ unregisterListener(SensorEventListener listener)665 public void unregisterListener(SensorEventListener listener) { 666 if (listener == null) { 667 return; 668 } 669 670 unregisterListenerImpl(listener, null); 671 } 672 673 /** @hide */ unregisterListenerImpl(SensorEventListener listener, Sensor sensor)674 protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor sensor); 675 676 /** 677 * 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. 711 * </p> 712 * 713 * @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. 724 * @see #registerListener(SensorEventListener, Sensor, int, Handler) 725 * @see #unregisterListener(SensorEventListener) 726 * @see #unregisterListener(SensorEventListener, Sensor) 727 */ registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs)728 public boolean registerListener(SensorEventListener listener, Sensor sensor, 729 int samplingPeriodUs) { 730 return registerListener(listener, sensor, samplingPeriodUs, null); 731 } 732 733 /** 734 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given 735 * sensor at the given sampling frequency and the given maximum reporting latency. 736 * <p> 737 * 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. 757 * </p> 758 * <p class="note"> 759 * </p> 760 * Note: Don't use this method with one-shot trigger sensors such as 761 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use 762 * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p> 763 * 764 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object 765 * 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. 768 * @param sensor The {@link android.hardware.Sensor Sensor} to register to. 769 * @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 772 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 773 * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in 774 * microseconds. 775 * @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 779 * {@link #registerListener(SensorEventListener, Sensor, int)}. 780 * @return <code>true</code> if the sensor is supported and successfully enabled. 781 * @see #registerListener(SensorEventListener, Sensor, int) 782 * @see #unregisterListener(SensorEventListener) 783 * @see #flush(SensorEventListener) 784 */ registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, int maxReportLatencyUs)785 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); 789 } 790 791 /** 792 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given 793 * sensor. Events are delivered in continuous mode as soon as they are available. To reduce the 794 * 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"> 798 * </p> 799 * 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> 802 * 803 * @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. 815 * @return <code>true</code> if the sensor is supported and successfully enabled. 816 * @see #registerListener(SensorEventListener, Sensor, int) 817 * @see #unregisterListener(SensorEventListener) 818 * @see #unregisterListener(SensorEventListener, Sensor) 819 */ registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, Handler handler)820 public boolean registerListener(SensorEventListener listener, Sensor sensor, 821 int samplingPeriodUs, Handler handler) { 822 int delay = getDelay(samplingPeriodUs); 823 return registerListenerImpl(listener, sensor, delay, handler, 0, 0); 824 } 825 826 /** 827 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given 828 * sensor at the given sampling frequency and the given maximum reporting latency. 829 * 830 * @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. 835 * @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 838 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 839 * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in 840 * microseconds. 841 * @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 845 * {@link #registerListener(SensorEventListener, Sensor, int)}. 846 * @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. 849 * @see #registerListener(SensorEventListener, Sensor, int, int) 850 */ registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, int maxReportLatencyUs, Handler handler)851 public boolean registerListener(SensorEventListener listener, Sensor sensor, 852 int samplingPeriodUs, int maxReportLatencyUs, Handler handler) { 853 int delayUs = getDelay(samplingPeriodUs); 854 return registerListenerImpl(listener, sensor, delayUs, handler, maxReportLatencyUs, 0); 855 } 856 857 /** @hide */ registerListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags)858 protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, 859 int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags); 860 861 862 /** 863 * 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 867 * 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. 881 */ flush(SensorEventListener listener)882 public boolean flush(SensorEventListener listener) { 883 return flushImpl(listener); 884 } 885 886 /** @hide */ flushImpl(SensorEventListener listener)887 protected abstract boolean flushImpl(SensorEventListener listener); 888 889 890 /** 891 * 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. 897 * 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. 903 * @return A {@link android.hardware.SensorDirectChannel} object. 904 * @throws NullPointerException when mem is null. 905 * @throws UncheckedIOException if not able to create channel. 906 * @see SensorDirectChannel#close() 907 */ createDirectChannel(MemoryFile mem)908 public SensorDirectChannel createDirectChannel(MemoryFile mem) { 909 return createDirectChannelImpl(mem, null); 910 } 911 912 /** 913 * 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. 919 * 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. 925 * @return A {@link android.hardware.SensorDirectChannel} object. 926 * @throws NullPointerException when mem is null. 927 * @throws UncheckedIOException if not able to create channel. 928 * @see SensorDirectChannel#close() 929 */ createDirectChannel(HardwareBuffer mem)930 public SensorDirectChannel createDirectChannel(HardwareBuffer mem) { 931 return createDirectChannelImpl(null, mem); 932 } 933 934 /** @hide */ createDirectChannelImpl( MemoryFile memoryFile, HardwareBuffer hardwareBuffer)935 protected abstract SensorDirectChannel createDirectChannelImpl( 936 MemoryFile memoryFile, HardwareBuffer hardwareBuffer); 937 938 /** @hide */ destroyDirectChannel(SensorDirectChannel channel)939 void destroyDirectChannel(SensorDirectChannel channel) { 940 destroyDirectChannelImpl(channel); 941 } 942 943 /** @hide */ destroyDirectChannelImpl(SensorDirectChannel channel)944 protected abstract void destroyDirectChannelImpl(SensorDirectChannel channel); 945 946 /** @hide */ configureDirectChannelImpl( SensorDirectChannel channel, Sensor s, int rate)947 protected abstract int configureDirectChannelImpl( 948 SensorDirectChannel channel, Sensor s, int rate); 949 950 /** 951 * Used for receiving notifications from the SensorManager when dynamic sensors are connected or 952 * disconnected. 953 */ 954 public abstract static class DynamicSensorCallback { 955 /** 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 */ onDynamicSensorConnected(Sensor sensor)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 */ onDynamicSensorDisconnected(Sensor sensor)967 public void onDynamicSensorDisconnected(Sensor sensor) {} 968 } 969 970 971 /** 972 * Add a {@link android.hardware.SensorManager.DynamicSensorCallback 973 * DynamicSensorCallback} to receive dynamic sensor connection callbacks. Repeat 974 * registration with the already registered callback object will have no additional effect. 975 * 976 * @param callback An object that implements the 977 * {@link android.hardware.SensorManager.DynamicSensorCallback 978 * DynamicSensorCallback} 979 * interface for receiving callbacks. 980 * @see #registerDynamicSensorCallback(DynamicSensorCallback, Handler) 981 * 982 * @throws IllegalArgumentException when callback is null. 983 */ registerDynamicSensorCallback(DynamicSensorCallback callback)984 public void registerDynamicSensorCallback(DynamicSensorCallback callback) { 985 registerDynamicSensorCallback(callback, null); 986 } 987 988 /** 989 * Add a {@link android.hardware.SensorManager.DynamicSensorCallback 990 * DynamicSensorCallback} to receive dynamic sensor connection callbacks. Repeat 991 * registration with the already registered callback object will have no additional effect. 992 * 993 * @param callback An object that implements the 994 * {@link android.hardware.SensorManager.DynamicSensorCallback 995 * DynamicSensorCallback} interface for receiving callbacks. 996 * @param handler The {@link android.os.Handler Handler} the {@link 997 * android.hardware.SensorManager.DynamicSensorCallback 998 * sensor connection events} will be delivered to. 999 * 1000 * @throws IllegalArgumentException when callback is null. 1001 */ registerDynamicSensorCallback( DynamicSensorCallback callback, Handler handler)1002 public void registerDynamicSensorCallback( 1003 DynamicSensorCallback callback, Handler handler) { 1004 registerDynamicSensorCallbackImpl(callback, handler); 1005 } 1006 1007 /** 1008 * Remove a {@link android.hardware.SensorManager.DynamicSensorCallback 1009 * DynamicSensorCallback} to stop sending dynamic sensor connection events to that 1010 * callback. 1011 * 1012 * @param callback An object that implements the 1013 * {@link android.hardware.SensorManager.DynamicSensorCallback 1014 * DynamicSensorCallback} 1015 * interface for receiving callbacks. 1016 */ unregisterDynamicSensorCallback(DynamicSensorCallback callback)1017 public void unregisterDynamicSensorCallback(DynamicSensorCallback callback) { 1018 unregisterDynamicSensorCallbackImpl(callback); 1019 } 1020 1021 /** 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 */ isDynamicSensorDiscoverySupported()1027 public boolean isDynamicSensorDiscoverySupported() { 1028 List<Sensor> sensors = getSensorList(Sensor.TYPE_DYNAMIC_SENSOR_META); 1029 return sensors.size() > 0; 1030 } 1031 1032 /** @hide */ registerDynamicSensorCallbackImpl( DynamicSensorCallback callback, Handler handler)1033 protected abstract void registerDynamicSensorCallbackImpl( 1034 DynamicSensorCallback callback, Handler handler); 1035 1036 /** @hide */ unregisterDynamicSensorCallbackImpl( DynamicSensorCallback callback)1037 protected abstract void unregisterDynamicSensorCallbackImpl( 1038 DynamicSensorCallback callback); 1039 1040 /** 1041 * <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> 1047 * 1048 * <ul> 1049 * <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> 1054 * </ul> 1055 * 1056 * <p> 1057 * <center><img src="../../../images/axis_globe.png" 1058 * alt="World coordinate-system diagram." border="0" /></center> 1059 * </p> 1060 * 1061 * <p> 1062 * <hr> 1063 * <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 1072 * 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. 1075 * 1076 * <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}. 1081 * <hr> 1082 * 1083 * <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> 1088 * 1089 * <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> 1095 * 1096 * 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 1102 * 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: 1107 * 1108 * <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> 1114 * 1115 * <p> 1116 * <u>If the array length is 9:</u> 1117 * 1118 * <pre> 1119 * / M[ 0] M[ 1] M[ 2] \ 1120 * | M[ 3] M[ 4] M[ 5] | 1121 * \ M[ 6] M[ 7] M[ 8] / 1122 *</pre> 1123 * 1124 * <hr> 1125 * <p> 1126 * The inverse of each matrix can be computed easily by taking its 1127 * transpose. 1128 * 1129 * <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. 1134 * 1135 * @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> 1139 * 1140 * @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> 1144 * 1145 * @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> 1154 * 1155 * @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}. 1163 * 1164 * @return <code>true</code> on success, <code>false</code> on failure (for 1165 * 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. 1168 * 1169 * @see #getInclination(float[]) 1170 * @see #getOrientation(float[], float[]) 1171 * @see #remapCoordinateSystem(float[], int, int, float[]) 1172 */ 1173 getRotationMatrix(float[] R, float[] I, float[] gravity, float[] geomagnetic)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]; 1180 1181 final float normsqA = (Ax * Ax + Ay * Ay + Az * Az); 1182 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 1189 final float Ex = geomagnetic[0]; 1190 final float Ey = geomagnetic[1]; 1191 final float Ez = geomagnetic[2]; 1192 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); 1196 1197 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; 1206 final float invA = 1.0f / (float) Math.sqrt(Ax * Ax + Ay * Ay + Az * Az); 1207 Ax *= invA; 1208 Ay *= invA; 1209 Az *= invA; 1210 final float Mx = Ay * Hz - Az * Hy; 1211 final float My = Az * Hx - Ax * Hz; 1212 final float Mz = Ax * Hy - Ay * Hx; 1213 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. 1229 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; 1232 if (I.length == 9) { 1233 I[0] = 1; I[1] = 0; I[2] = 0; 1234 I[3] = 0; I[4] = c; I[5] = s; 1235 I[6] = 0; I[7] = -s; I[8] = c; 1236 } 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; 1239 I[8] = 0; I[9] = -s; I[10] = c; 1240 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}. 1250 * 1251 * @param I 1252 * inclination matrix see {@link #getRotationMatrix}. 1253 * 1254 * @return The geomagnetic inclination angle in radians. 1255 * 1256 * @see #getRotationMatrix(float[], float[], float[], float[]) 1257 * @see #getOrientation(float[], float[]) 1258 * @see GeomagneticField 1259 * 1260 */ getInclination(float[] I)1261 public static float getInclination(float[] I) { 1262 if (I.length == 9) { 1263 return (float) Math.atan2(I[5], I[4]); 1264 } else { 1265 return (float) Math.atan2(I[6], I[5]); 1266 } 1267 } 1268 1269 /** 1270 * <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 1274 * {@link #getOrientation}) in a different coordinate system. 1275 * </p> 1276 * 1277 * <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> 1286 * 1287 * <p> 1288 * <u>Examples:</u> 1289 * <p> 1290 * 1291 * <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> 1294 * 1295 * <p> 1296 * <ul> 1297 * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code> 1298 * </ul> 1299 * </p> 1300 * 1301 * <li>Using the device as a mechanical compass when rotation is 1302 * {@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:</li> 1303 * 1304 * <p> 1305 * <ul> 1306 * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code> 1307 * </ul> 1308 * </p> 1309 * 1310 * 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> 1316 * 1317 * <p> 1318 * Since the resulting coordinate system is orthonormal, only two axes need 1319 * to be specified. 1320 * 1321 * @param inR 1322 * the rotation matrix to be transformed. Usually it is the matrix 1323 * returned by {@link #getRotationMatrix}. 1324 * 1325 * @param X 1326 * defines the axis of the new cooridinate system that coincide with the X axis of the 1327 * original coordinate system. 1328 * 1329 * @param Y 1330 * defines the axis of the new cooridinate system that coincide with the Y axis of the 1331 * original coordinate system. 1332 * 1333 * @param outR 1334 * the transformed rotation matrix. inR and outR should not be the same 1335 * array. 1336 * 1337 * @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. 1340 * 1341 * @see #getRotationMatrix(float[], float[], float[], float[]) 1342 */ 1343 remapCoordinateSystem(float[] inR, int X, int Y, float[] outR)1344 public static boolean remapCoordinateSystem(float[] inR, int X, int Y, float[] outR) { 1345 if (inR == outR) { 1346 final float[] temp = sTempMatrix; 1347 synchronized (temp) { 1348 // we don't expect to have a lot of contention 1349 if (remapCoordinateSystemImpl(inR, X, Y, temp)) { 1350 final int size = outR.length; 1351 for (int i = 0; i < size; i++) { 1352 outR[i] = temp[i]; 1353 } 1354 return true; 1355 } 1356 } 1357 } 1358 return remapCoordinateSystemImpl(inR, X, Y, outR); 1359 } 1360 remapCoordinateSystemImpl(float[] inR, int X, int Y, float[] outR)1361 private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y, float[] outR) { 1362 /* 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; 1374 if (inR.length != length) { 1375 return false; // invalid parameter 1376 } 1377 if ((X & 0x7C) != 0 || (Y & 0x7C) != 0) { 1378 return false; // invalid parameter 1379 } 1380 if (((X & 0x3) == 0) || ((Y & 0x3) == 0)) { 1381 return false; // no axis specified 1382 } 1383 if ((X & 0x3) == (Y & 0x3)) { 1384 return false; // same axis specified 1385 } 1386 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. 1393 final int x = (X & 0x3) - 1; 1394 final int y = (Y & 0x3) - 1; 1395 final int z = (Z & 0x3) - 1; 1396 1397 // compute the sign of Z (whether it needs to be inverted) 1398 final int axis_y = (z + 1) % 3; 1399 final int axis_z = (z + 2) % 3; 1400 if (((x ^ axis_y) | (y ^ axis_z)) != 0) { 1401 Z ^= 0x80; 1402 } 1403 1404 final boolean sx = (X >= 0x80); 1405 final boolean sy = (Y >= 0x80); 1406 final boolean sz = (Z >= 0x80); 1407 1408 // Perform R * r, in avoiding actual muls and adds. 1409 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]; 1416 } 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. 1427 * <p> 1428 * When it returns, the array values are as follows: 1429 * <ul> 1430 * <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 π. 1434 * Likewise, when facing east, this angle is π/2, and 1435 * when facing west, this angle is -π/2. The range of 1436 * values is -π to π.</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 -π to π.</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 -π/2 to π/2.</li> 1451 * </ul> 1452 * <p> 1453 * 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>. 1457 * 1458 * @param R 1459 * rotation matrix see {@link #getRotationMatrix}. 1460 * 1461 * @param values 1462 * an array of 3 floats to hold the result. 1463 * 1464 * @return The array values passed as argument. 1465 * 1466 * @see #getRotationMatrix(float[], float[], float[], float[]) 1467 * @see GeomagneticField 1468 */ getOrientation(float[] R, float[] values)1469 public static float[] getOrientation(float[] R, float[] values) { 1470 /* 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 / 1476 * 1477 * 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] / 1481 * 1482 */ 1483 if (R.length == 9) { 1484 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]); 1487 } else { 1488 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]); 1491 } 1492 1493 return values; 1494 } 1495 1496 /** 1497 * 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 1503 * 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> 1519 * </p> 1520 * 1521 * @param p0 pressure at sea level 1522 * @param p atmospheric pressure 1523 * @return Altitude in meters 1524 */ getAltitude(float p0, float p)1525 public static float getAltitude(float p0, float p) { 1526 final float coef = 1.0f / 5.255f; 1527 return 44330.0f * (1.0f - (float) Math.pow(p / p0, coef)); 1528 } 1529 1530 /** Helper function to compute the angle change between two rotation matrices. 1531 * Given a current rotation matrix (R) and a previous rotation matrix 1532 * (prevR) computes the intrinsic rotation around the z, x, and y axes which 1533 * transforms prevR to R. 1534 * outputs a 3 element vector containing the z, x, and y angle 1535 * 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> 1551 * 1552 * See {@link #getOrientation} for more detailed definition of the output. 1553 * 1554 * @param R current rotation matrix 1555 * @param prevR previous rotation matrix 1556 * @param angleChange an an array of floats (z, x, and y) in which the angle change 1557 * (in radians) is stored 1558 */ 1559 getAngleChange(float[] angleChange, float[] R, float[] prevR)1560 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; 1565 1566 if (R.length == 9) { 1567 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]; 1576 } else if (R.length == 16) { 1577 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 1588 if (prevR.length == 9) { 1589 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]; 1598 } else if (prevR.length == 16) { 1599 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]; 1608 } 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 1619 angleChange[0] = (float) Math.atan2(rd1, rd4); 1620 angleChange[1] = (float) Math.asin(-rd7); 1621 angleChange[2] = (float) Math.atan2(-rd6, rd8); 1622 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 */ getRotationMatrixFromVector(float[] R, float[] rotationVector)1644 public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) { 1645 1646 float q0; 1647 float q1 = rotationVector[0]; 1648 float q2 = rotationVector[1]; 1649 float q3 = rotationVector[2]; 1650 1651 if (rotationVector.length >= 4) { 1652 q0 = rotationVector[3]; 1653 } else { 1654 q0 = 1 - q1 * q1 - q2 * q2 - q3 * q3; 1655 q0 = (q0 > 0) ? (float) Math.sqrt(q0) : 0; 1656 } 1657 1658 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 1668 if (R.length == 9) { 1669 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 */ getQuaternionFromVector(float[] Q, float[] rv)1707 public static void getQuaternionFromVector(float[] Q, float[] rv) { 1708 if (rv.length >= 4) { 1709 Q[0] = rv[3]; 1710 } else { 1711 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; 1713 } 1714 Q[1] = rv[0]; 1715 Q[2] = rv[1]; 1716 Q[3] = rv[2]; 1717 } 1718 1719 /** 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 */ requestTriggerSensor(TriggerEventListener listener, Sensor sensor)1738 public boolean requestTriggerSensor(TriggerEventListener listener, Sensor sensor) { 1739 return requestTriggerSensorImpl(listener, sensor); 1740 } 1741 1742 /** 1743 * @hide 1744 */ requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor)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 */ cancelTriggerSensor(TriggerEventListener listener, Sensor sensor)1770 public boolean cancelTriggerSensor(TriggerEventListener listener, Sensor sensor) { 1771 return cancelTriggerSensorImpl(listener, sensor, true); 1772 } 1773 1774 /** 1775 * @hide 1776 */ cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor, boolean disable)1777 protected abstract boolean cancelTriggerSensorImpl(TriggerEventListener listener, 1778 Sensor sensor, boolean disable); 1779 1780 1781 /** 1782 * For testing purposes only. Not for third party applications. 1783 * 1784 * 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. 1794 * 1795 * @param enable True to initialize a client in DATA_INJECTION mode. 1796 * False to clean up the native resources. 1797 * 1798 * @return true if the HAL supports data injection and false 1799 * otherwise. 1800 * @hide 1801 */ 1802 @SystemApi initDataInjection(boolean enable)1803 public boolean initDataInjection(boolean enable) { 1804 return initDataInjectionImpl(enable); 1805 } 1806 1807 /** 1808 * @hide 1809 */ initDataInjectionImpl(boolean enable)1810 protected abstract boolean initDataInjectionImpl(boolean enable); 1811 1812 /** 1813 * For testing purposes only. Not for third party applications. 1814 * 1815 * 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. 1819 * 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 injectSensorData(Sensor sensor, float[] values, int accuracy, long timestamp)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 } 1848 int expectedNumValues = Sensor.getMaxLengthValuesArray(sensor, Build.VERSION_CODES.M); 1849 if (values.length != expectedNumValues) { 1850 throw new IllegalArgumentException("Wrong number of values for sensor " 1851 + sensor.getName() + " actual=" + values.length + " expected=" 1852 + expectedNumValues); 1853 } 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 } 1860 return injectSensorDataImpl(sensor, values, accuracy, timestamp); 1861 } 1862 1863 /** 1864 * @hide 1865 */ injectSensorDataImpl(Sensor sensor, float[] values, int accuracy, long timestamp)1866 protected abstract boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy, 1867 long timestamp); 1868 getLegacySensorManager()1869 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); 1875 } 1876 return mLegacySensorManager; 1877 } 1878 } 1879 getDelay(int rate)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 } 1901 1902 /** @hide */ setOperationParameter(SensorAdditionalInfo parameter)1903 public boolean setOperationParameter(SensorAdditionalInfo parameter) { 1904 return setOperationParameterImpl(parameter); 1905 } 1906 1907 /** @hide */ setOperationParameterImpl(SensorAdditionalInfo parameter)1908 protected abstract boolean setOperationParameterImpl(SensorAdditionalInfo parameter); 1909 } 1910