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