SensorManager.java revision 18ebf732b84d0575c871db35b25bf000e0c7c6a6
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 17package android.hardware; 18 19import android.annotation.SystemApi; 20import android.os.Build; 21import android.os.Handler; 22import android.os.SystemClock; 23import android.util.Log; 24import android.util.SparseArray; 25 26import java.util.ArrayList; 27import java.util.Collections; 28import java.util.List; 29 30/** 31 * <p> 32 * SensorManager lets you access the device's {@link android.hardware.Sensor 33 * sensors}. Get an instance of this class by calling 34 * {@link android.content.Context#getSystemService(java.lang.String) 35 * Context.getSystemService()} with the argument 36 * {@link android.content.Context#SENSOR_SERVICE}. 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 */ 82public abstract class SensorManager { 83 /** @hide */ 84 protected static final String TAG = "SensorManager"; 85 86 private static final float[] mTempMatrix = 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 */ 371 public SensorManager() { 372 } 373 374 /** 375 * Gets the full list of sensors that are available. 376 * @hide 377 */ 378 protected abstract List<Sensor> getFullSensorList(); 379 380 /** 381 * @return available sensors. 382 * @deprecated This method is deprecated, use 383 * {@link SensorManager#getSensorList(int)} instead 384 */ 385 @Deprecated 386 public int getSensors() { 387 return getLegacySensorManager().getSensors(); 388 } 389 390 /** 391 * Use this method to get the list of available sensors of a certain type. 392 * Make multiple calls to get sensors of different types or use 393 * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the 394 * sensors. 395 * 396 * <p class="note"> 397 * NOTE: Both wake-up and non wake-up sensors matching the given type are 398 * returned. Check {@link Sensor#isWakeUpSensor()} to know the wake-up properties 399 * of the returned {@link Sensor}. 400 * </p> 401 * 402 * @param type 403 * of sensors requested 404 * 405 * @return a list of sensors matching the asked type. 406 * 407 * @see #getDefaultSensor(int) 408 * @see Sensor 409 */ 410 public List<Sensor> getSensorList(int type) { 411 // cache the returned lists the first time 412 List<Sensor> list; 413 final List<Sensor> fullList = getFullSensorList(); 414 synchronized (mSensorListByType) { 415 list = mSensorListByType.get(type); 416 if (list == null) { 417 if (type == Sensor.TYPE_ALL) { 418 list = fullList; 419 } else { 420 list = new ArrayList<Sensor>(); 421 for (Sensor i : fullList) { 422 if (i.getType() == type) 423 list.add(i); 424 } 425 } 426 list = Collections.unmodifiableList(list); 427 mSensorListByType.append(type, list); 428 } 429 } 430 return list; 431 } 432 433 /** 434 * Use this method to get the default sensor for a given type. Note that the 435 * returned sensor could be a composite sensor, and its data could be 436 * averaged or filtered. If you need to access the raw sensors use 437 * {@link SensorManager#getSensorList(int) getSensorList}. 438 * 439 * @param type 440 * of sensors requested 441 * 442 * @return the default sensor matching the requested type if one exists and the application 443 * has the necessary permissions, or null otherwise. 444 * 445 * @see #getSensorList(int) 446 * @see Sensor 447 */ 448 public Sensor getDefaultSensor(int type) { 449 // TODO: need to be smarter, for now, just return the 1st sensor 450 List<Sensor> l = getSensorList(type); 451 boolean wakeUpSensor = false; 452 // For the following sensor types, return a wake-up sensor. These types are by default 453 // defined as wake-up sensors. For the rest of the SDK defined sensor types return a 454 // non_wake-up version. 455 if (type == Sensor.TYPE_PROXIMITY || type == Sensor.TYPE_SIGNIFICANT_MOTION || 456 type == Sensor.TYPE_TILT_DETECTOR || type == Sensor.TYPE_WAKE_GESTURE || 457 type == Sensor.TYPE_GLANCE_GESTURE || type == Sensor.TYPE_PICK_UP_GESTURE || 458 type == Sensor.TYPE_WRIST_TILT_GESTURE) { 459 wakeUpSensor = true; 460 } 461 462 for (Sensor sensor : l) { 463 if (sensor.isWakeUpSensor() == wakeUpSensor) return sensor; 464 } 465 return null; 466 } 467 468 /** 469 * Return a Sensor with the given type and wakeUp properties. If multiple sensors of this 470 * type exist, any one of them may be returned. 471 * <p> 472 * For example, 473 * <ul> 474 * <li>getDefaultSensor({@link Sensor#TYPE_ACCELEROMETER}, true) returns a wake-up accelerometer 475 * sensor if it exists. </li> 476 * <li>getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, false) returns a non wake-up proximity 477 * sensor if it exists. </li> 478 * <li>getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, true) returns a wake-up proximity sensor 479 * which is the same as the Sensor returned by {@link #getDefaultSensor(int)}. </li> 480 * </ul> 481 * </p> 482 * <p class="note"> 483 * Note: Sensors like {@link Sensor#TYPE_PROXIMITY} and {@link Sensor#TYPE_SIGNIFICANT_MOTION} 484 * are declared as wake-up sensors by default. 485 * </p> 486 * @param type 487 * type of sensor requested 488 * @param wakeUp 489 * flag to indicate whether the Sensor is a wake-up or non wake-up sensor. 490 * @return the default sensor matching the requested type and wakeUp properties if one exists 491 * and the application has the necessary permissions, or null otherwise. 492 * @see Sensor#isWakeUpSensor() 493 */ 494 public Sensor getDefaultSensor(int type, boolean wakeUp) { 495 List<Sensor> l = getSensorList(type); 496 for (Sensor sensor : l) { 497 if (sensor.isWakeUpSensor() == wakeUp) 498 return sensor; 499 } 500 return null; 501 } 502 503 /** 504 * Registers a listener for given sensors. 505 * 506 * @deprecated This method is deprecated, use 507 * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)} 508 * instead. 509 * 510 * @param listener 511 * sensor listener object 512 * 513 * @param sensors 514 * a bit masks of the sensors to register to 515 * 516 * @return <code>true</code> if the sensor is supported and successfully 517 * enabled 518 */ 519 @Deprecated 520 public boolean registerListener(SensorListener listener, int sensors) { 521 return registerListener(listener, sensors, SENSOR_DELAY_NORMAL); 522 } 523 524 /** 525 * Registers a SensorListener for given sensors. 526 * 527 * @deprecated This method is deprecated, use 528 * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)} 529 * instead. 530 * 531 * @param listener 532 * sensor listener object 533 * 534 * @param sensors 535 * a bit masks of the sensors to register to 536 * 537 * @param rate 538 * rate of events. This is only a hint to the system. events may be 539 * received faster or slower than the specified rate. Usually events 540 * are received faster. The value must be one of 541 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 542 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}. 543 * 544 * @return <code>true</code> if the sensor is supported and successfully 545 * enabled 546 */ 547 @Deprecated 548 public boolean registerListener(SensorListener listener, int sensors, int rate) { 549 return getLegacySensorManager().registerListener(listener, sensors, rate); 550 } 551 552 /** 553 * Unregisters a listener for all sensors. 554 * 555 * @deprecated This method is deprecated, use 556 * {@link SensorManager#unregisterListener(SensorEventListener)} 557 * instead. 558 * 559 * @param listener 560 * a SensorListener object 561 */ 562 @Deprecated 563 public void unregisterListener(SensorListener listener) { 564 unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW); 565 } 566 567 /** 568 * Unregisters a listener for the sensors with which it is registered. 569 * 570 * @deprecated This method is deprecated, use 571 * {@link SensorManager#unregisterListener(SensorEventListener, Sensor)} 572 * instead. 573 * 574 * @param listener 575 * a SensorListener object 576 * 577 * @param sensors 578 * a bit masks of the sensors to unregister from 579 */ 580 @Deprecated 581 public void unregisterListener(SensorListener listener, int sensors) { 582 getLegacySensorManager().unregisterListener(listener, sensors); 583 } 584 585 /** 586 * Unregisters a listener for the sensors with which it is registered. 587 * 588 * <p class="note"></p> 589 * Note: Don't use this method with a one shot trigger sensor such as 590 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. 591 * Use {@link #cancelTriggerSensor(TriggerEventListener, Sensor)} instead. 592 * </p> 593 * 594 * @param listener 595 * a SensorEventListener object 596 * 597 * @param sensor 598 * the sensor to unregister from 599 * 600 * @see #unregisterListener(SensorEventListener) 601 * @see #registerListener(SensorEventListener, Sensor, int) 602 */ 603 public void unregisterListener(SensorEventListener listener, Sensor sensor) { 604 if (listener == null || sensor == null) { 605 return; 606 } 607 608 unregisterListenerImpl(listener, sensor); 609 } 610 611 /** 612 * Unregisters a listener for all sensors. 613 * 614 * @param listener 615 * a SensorListener object 616 * 617 * @see #unregisterListener(SensorEventListener, Sensor) 618 * @see #registerListener(SensorEventListener, Sensor, int) 619 * 620 */ 621 public void unregisterListener(SensorEventListener listener) { 622 if (listener == null) { 623 return; 624 } 625 626 unregisterListenerImpl(listener, null); 627 } 628 629 /** @hide */ 630 protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor sensor); 631 632 /** 633 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given 634 * sensor at the given sampling frequency. 635 * <p> 636 * The events will be delivered to the provided {@code SensorEventListener} as soon as they are 637 * available. To reduce the power consumption, applications can use 638 * {@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a 639 * positive non-zero maximum reporting latency. 640 * </p> 641 * <p> 642 * In the case of non-wake-up sensors, the events are only delivered while the Application 643 * Processor (AP) is not in suspend mode. See {@link Sensor#isWakeUpSensor()} for more details. 644 * To ensure delivery of events from non-wake-up sensors even when the screen is OFF, the 645 * application registering to the sensor must hold a partial wake-lock to keep the AP awake, 646 * otherwise some events might be lost while the AP is asleep. Note that although events might 647 * be lost while the AP is asleep, the sensor will still consume power if it is not explicitly 648 * deactivated by the application. Applications must unregister their {@code 649 * SensorEventListener}s in their activity's {@code onPause()} method to avoid consuming power 650 * while the device is inactive. See {@link #registerListener(SensorEventListener, Sensor, int, 651 * int)} for more details on hardware FIFO (queueing) capabilities and when some sensor events 652 * might be lost. 653 * </p> 654 * <p> 655 * In the case of wake-up sensors, each event generated by the sensor will cause the AP to 656 * wake-up, ensuring that each event can be delivered. Because of this, registering to a wake-up 657 * sensor has very significant power implications. Call {@link Sensor#isWakeUpSensor()} to check 658 * whether a sensor is a wake-up sensor. See 659 * {@link #registerListener(SensorEventListener, Sensor, int, int)} for information on how to 660 * reduce the power impact of registering to wake-up sensors. 661 * </p> 662 * <p class="note"> 663 * Note: Don't use this method with one-shot trigger sensors such as 664 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use 665 * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. Use 666 * {@link Sensor#getReportingMode()} to obtain the reporting mode of a given sensor. 667 * </p> 668 * 669 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object. 670 * @param sensor The {@link android.hardware.Sensor Sensor} to register to. 671 * @param samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are 672 * delivered at. This is only a hint to the system. Events may be received faster or 673 * slower than the specified rate. Usually events are received faster. The value must 674 * be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 675 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired delay 676 * between events in microseconds. Specifying the delay in microseconds only works 677 * from Android 2.3 (API level 9) onwards. For earlier releases, you must use one of 678 * the {@code SENSOR_DELAY_*} constants. 679 * @return <code>true</code> if the sensor is supported and successfully enabled. 680 * @see #registerListener(SensorEventListener, Sensor, int, Handler) 681 * @see #unregisterListener(SensorEventListener) 682 * @see #unregisterListener(SensorEventListener, Sensor) 683 */ 684 public boolean registerListener(SensorEventListener listener, Sensor sensor, 685 int samplingPeriodUs) { 686 return registerListener(listener, sensor, samplingPeriodUs, null); 687 } 688 689 /** 690 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given 691 * sensor at the given sampling frequency and the given maximum reporting latency. 692 * <p> 693 * This function is similar to {@link #registerListener(SensorEventListener, Sensor, int)} but 694 * it allows events to stay temporarily in the hardware FIFO (queue) before being delivered. The 695 * events can be stored in the hardware FIFO up to {@code maxReportLatencyUs} microseconds. Once 696 * one of the events in the FIFO needs to be reported, all of the events in the FIFO are 697 * reported sequentially. This means that some events will be reported before the maximum 698 * reporting latency has elapsed. 699 * </p><p> 700 * When {@code maxReportLatencyUs} is 0, the call is equivalent to a call to 701 * {@link #registerListener(SensorEventListener, Sensor, int)}, as it requires the events to be 702 * delivered as soon as possible. 703 * </p><p> 704 * When {@code sensor.maxFifoEventCount()} is 0, the sensor does not use a FIFO, so the call 705 * will also be equivalent to {@link #registerListener(SensorEventListener, Sensor, int)}. 706 * </p><p> 707 * Setting {@code maxReportLatencyUs} to a positive value allows to reduce the number of 708 * interrupts the AP (Application Processor) receives, hence reducing power consumption, as the 709 * AP can switch to a lower power state while the sensor is capturing the data. This is 710 * especially important when registering to wake-up sensors, for which each interrupt causes the 711 * AP to wake up if it was in suspend mode. See {@link Sensor#isWakeUpSensor()} for more 712 * information on wake-up sensors. 713 * </p> 714 * <p class="note"> 715 * </p> 716 * Note: Don't use this method with one-shot trigger sensors such as 717 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use 718 * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p> 719 * 720 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object 721 * that will receive the sensor events. If the application is interested in receiving 722 * flush complete notifications, it should register with 723 * {@link android.hardware.SensorEventListener SensorEventListener2} instead. 724 * @param sensor The {@link android.hardware.Sensor Sensor} to register to. 725 * @param samplingPeriodUs The desired delay between two consecutive events in microseconds. 726 * This is only a hint to the system. Events may be received faster or slower than 727 * the specified rate. Usually events are received faster. Can be one of 728 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 729 * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in 730 * microseconds. 731 * @param maxReportLatencyUs Maximum time in microseconds that events can be delayed before 732 * being reported to the application. A large value allows reducing the power 733 * consumption associated with the sensor. If maxReportLatencyUs is set to zero, 734 * events are delivered as soon as they are available, which is equivalent to calling 735 * {@link #registerListener(SensorEventListener, Sensor, int)}. 736 * @return <code>true</code> if the sensor is supported and successfully enabled. 737 * @see #registerListener(SensorEventListener, Sensor, int) 738 * @see #unregisterListener(SensorEventListener) 739 * @see #flush(SensorEventListener) 740 */ 741 public boolean registerListener(SensorEventListener listener, Sensor sensor, 742 int samplingPeriodUs, int maxReportLatencyUs) { 743 int delay = getDelay(samplingPeriodUs); 744 return registerListenerImpl(listener, sensor, delay, null, maxReportLatencyUs, 0); 745 } 746 747 /** 748 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given 749 * sensor. Events are delivered in continuous mode as soon as they are available. To reduce the 750 * power consumption, applications can use 751 * {@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a 752 * positive non-zero maximum reporting latency. 753 * <p class="note"> 754 * </p> 755 * Note: Don't use this method with a one shot trigger sensor such as 756 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use 757 * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p> 758 * 759 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object. 760 * @param sensor The {@link android.hardware.Sensor Sensor} to register to. 761 * @param samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are 762 * delivered at. This is only a hint to the system. Events may be received faster or 763 * slower than the specified rate. Usually events are received faster. The value must 764 * be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 765 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired 766 * delay between events in microseconds. Specifying the delay in microseconds only 767 * works from Android 2.3 (API level 9) onwards. For earlier releases, you must use 768 * one of the {@code SENSOR_DELAY_*} constants. 769 * @param handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent 770 * sensor events} will be delivered to. 771 * @return <code>true</code> if the sensor is supported and successfully enabled. 772 * @see #registerListener(SensorEventListener, Sensor, int) 773 * @see #unregisterListener(SensorEventListener) 774 * @see #unregisterListener(SensorEventListener, Sensor) 775 */ 776 public boolean registerListener(SensorEventListener listener, Sensor sensor, 777 int samplingPeriodUs, Handler handler) { 778 int delay = getDelay(samplingPeriodUs); 779 return registerListenerImpl(listener, sensor, delay, handler, 0, 0); 780 } 781 782 /** 783 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given 784 * sensor at the given sampling frequency and the given maximum reporting latency. 785 * 786 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object 787 * that will receive the sensor events. If the application is interested in receiving 788 * flush complete notifications, it should register with 789 * {@link android.hardware.SensorEventListener SensorEventListener2} instead. 790 * @param sensor The {@link android.hardware.Sensor Sensor} to register to. 791 * @param samplingPeriodUs The desired delay between two consecutive events in microseconds. 792 * This is only a hint to the system. Events may be received faster or slower than 793 * the specified rate. Usually events are received faster. Can be one of 794 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 795 * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in 796 * microseconds. 797 * @param maxReportLatencyUs Maximum time in microseconds that events can be delayed before 798 * being reported to the application. A large value allows reducing the power 799 * consumption associated with the sensor. If maxReportLatencyUs is set to zero, 800 * events are delivered as soon as they are available, which is equivalent to calling 801 * {@link #registerListener(SensorEventListener, Sensor, int)}. 802 * @param handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent 803 * sensor events} will be delivered to. 804 * @return <code>true</code> if the sensor is supported and successfully enabled. 805 * @see #registerListener(SensorEventListener, Sensor, int, int) 806 */ 807 public boolean registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, 808 int maxReportLatencyUs, Handler handler) { 809 int delayUs = getDelay(samplingPeriodUs); 810 return registerListenerImpl(listener, sensor, delayUs, handler, maxReportLatencyUs, 0); 811 } 812 813 /** @hide */ 814 protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, 815 int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags); 816 817 818 /** 819 * Flushes the FIFO of all the sensors registered for this listener. If there are events 820 * in the FIFO of the sensor, they are returned as if the maxReportLantecy of the FIFO has 821 * expired. Events are returned in the usual way through the SensorEventListener. 822 * This call doesn't affect the maxReportLantecy for this sensor. This call is asynchronous and 823 * returns immediately. 824 * {@link android.hardware.SensorEventListener2#onFlushCompleted onFlushCompleted} is called 825 * after all the events in the batch at the time of calling this method have been delivered 826 * successfully. If the hardware doesn't support flush, it still returns true and a trivial 827 * flush complete event is sent after the current event for all the clients registered for this 828 * sensor. 829 * 830 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object 831 * which was previously used in a registerListener call. 832 * @return <code>true</code> if the flush is initiated successfully on all the sensors 833 * registered for this listener, false if no sensor is previously registered for this 834 * listener or flush on one of the sensors fails. 835 * @see #registerListener(SensorEventListener, Sensor, int, int) 836 * @throws IllegalArgumentException when listener is null. 837 */ 838 public boolean flush(SensorEventListener listener) { 839 return flushImpl(listener); 840 } 841 842 /** @hide */ 843 protected abstract boolean flushImpl(SensorEventListener listener); 844 845 /** 846 * <p> 847 * Computes the inclination matrix <b>I</b> as well as the rotation matrix 848 * <b>R</b> transforming a vector from the device coordinate system to the 849 * world's coordinate system which is defined as a direct orthonormal basis, 850 * where: 851 * </p> 852 * 853 * <ul> 854 * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to 855 * the ground at the device's current location and roughly points East).</li> 856 * <li>Y is tangential to the ground at the device's current location and 857 * points towards the magnetic North Pole.</li> 858 * <li>Z points towards the sky and is perpendicular to the ground.</li> 859 * </ul> 860 * 861 * <p> 862 * <center><img src="../../../images/axis_globe.png" 863 * alt="World coordinate-system diagram." border="0" /></center> 864 * </p> 865 * 866 * <p> 867 * <hr> 868 * <p> 869 * By definition: 870 * <p> 871 * [0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity) 872 * <p> 873 * [0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b> (m = magnitude of 874 * geomagnetic field) 875 * <p> 876 * <b>R</b> is the identity matrix when the device is aligned with the 877 * world's coordinate system, that is, when the device's X axis points 878 * toward East, the Y axis points to the North Pole and the device is facing 879 * the sky. 880 * 881 * <p> 882 * <b>I</b> is a rotation matrix transforming the geomagnetic vector into 883 * the same coordinate space as gravity (the world's coordinate space). 884 * <b>I</b> is a simple rotation around the X axis. The inclination angle in 885 * radians can be computed with {@link #getInclination}. 886 * <hr> 887 * 888 * <p> 889 * Each matrix is returned either as a 3x3 or 4x4 row-major matrix depending 890 * on the length of the passed array: 891 * <p> 892 * <u>If the array length is 16:</u> 893 * 894 * <pre> 895 * / M[ 0] M[ 1] M[ 2] M[ 3] \ 896 * | M[ 4] M[ 5] M[ 6] M[ 7] | 897 * | M[ 8] M[ 9] M[10] M[11] | 898 * \ M[12] M[13] M[14] M[15] / 899 *</pre> 900 * 901 * This matrix is ready to be used by OpenGL ES's 902 * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int) 903 * glLoadMatrixf(float[], int)}. 904 * <p> 905 * Note that because OpenGL matrices are column-major matrices you must 906 * transpose the matrix before using it. However, since the matrix is a 907 * rotation matrix, its transpose is also its inverse, conveniently, it is 908 * often the inverse of the rotation that is needed for rendering; it can 909 * therefore be used with OpenGL ES directly. 910 * <p> 911 * Also note that the returned matrices always have this form: 912 * 913 * <pre> 914 * / M[ 0] M[ 1] M[ 2] 0 \ 915 * | M[ 4] M[ 5] M[ 6] 0 | 916 * | M[ 8] M[ 9] M[10] 0 | 917 * \ 0 0 0 1 / 918 *</pre> 919 * 920 * <p> 921 * <u>If the array length is 9:</u> 922 * 923 * <pre> 924 * / M[ 0] M[ 1] M[ 2] \ 925 * | M[ 3] M[ 4] M[ 5] | 926 * \ M[ 6] M[ 7] M[ 8] / 927 *</pre> 928 * 929 * <hr> 930 * <p> 931 * The inverse of each matrix can be computed easily by taking its 932 * transpose. 933 * 934 * <p> 935 * The matrices returned by this function are meaningful only when the 936 * device is not free-falling and it is not close to the magnetic north. If 937 * the device is accelerating, or placed into a strong magnetic field, the 938 * returned matrices may be inaccurate. 939 * 940 * @param R 941 * is an array of 9 floats holding the rotation matrix <b>R</b> when 942 * this function returns. R can be null. 943 * <p> 944 * 945 * @param I 946 * is an array of 9 floats holding the rotation matrix <b>I</b> when 947 * this function returns. I can be null. 948 * <p> 949 * 950 * @param gravity 951 * is an array of 3 floats containing the gravity vector expressed in 952 * the device's coordinate. You can simply use the 953 * {@link android.hardware.SensorEvent#values values} returned by a 954 * {@link android.hardware.SensorEvent SensorEvent} of a 955 * {@link android.hardware.Sensor Sensor} of type 956 * {@link android.hardware.Sensor#TYPE_ACCELEROMETER 957 * TYPE_ACCELEROMETER}. 958 * <p> 959 * 960 * @param geomagnetic 961 * is an array of 3 floats containing the geomagnetic vector 962 * expressed in the device's coordinate. You can simply use the 963 * {@link android.hardware.SensorEvent#values values} returned by a 964 * {@link android.hardware.SensorEvent SensorEvent} of a 965 * {@link android.hardware.Sensor Sensor} of type 966 * {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD 967 * TYPE_MAGNETIC_FIELD}. 968 * 969 * @return <code>true</code> on success, <code>false</code> on failure (for 970 * instance, if the device is in free fall). On failure the output 971 * matrices are not modified. 972 * 973 * @see #getInclination(float[]) 974 * @see #getOrientation(float[], float[]) 975 * @see #remapCoordinateSystem(float[], int, int, float[]) 976 */ 977 978 public static boolean getRotationMatrix(float[] R, float[] I, 979 float[] gravity, float[] geomagnetic) { 980 // TODO: move this to native code for efficiency 981 float Ax = gravity[0]; 982 float Ay = gravity[1]; 983 float Az = gravity[2]; 984 final float Ex = geomagnetic[0]; 985 final float Ey = geomagnetic[1]; 986 final float Ez = geomagnetic[2]; 987 float Hx = Ey*Az - Ez*Ay; 988 float Hy = Ez*Ax - Ex*Az; 989 float Hz = Ex*Ay - Ey*Ax; 990 final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz); 991 if (normH < 0.1f) { 992 // device is close to free fall (or in space?), or close to 993 // magnetic north pole. Typical values are > 100. 994 return false; 995 } 996 final float invH = 1.0f / normH; 997 Hx *= invH; 998 Hy *= invH; 999 Hz *= invH; 1000 final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az); 1001 Ax *= invA; 1002 Ay *= invA; 1003 Az *= invA; 1004 final float Mx = Ay*Hz - Az*Hy; 1005 final float My = Az*Hx - Ax*Hz; 1006 final float Mz = Ax*Hy - Ay*Hx; 1007 if (R != null) { 1008 if (R.length == 9) { 1009 R[0] = Hx; R[1] = Hy; R[2] = Hz; 1010 R[3] = Mx; R[4] = My; R[5] = Mz; 1011 R[6] = Ax; R[7] = Ay; R[8] = Az; 1012 } else if (R.length == 16) { 1013 R[0] = Hx; R[1] = Hy; R[2] = Hz; R[3] = 0; 1014 R[4] = Mx; R[5] = My; R[6] = Mz; R[7] = 0; 1015 R[8] = Ax; R[9] = Ay; R[10] = Az; R[11] = 0; 1016 R[12] = 0; R[13] = 0; R[14] = 0; R[15] = 1; 1017 } 1018 } 1019 if (I != null) { 1020 // compute the inclination matrix by projecting the geomagnetic 1021 // vector onto the Z (gravity) and X (horizontal component 1022 // of geomagnetic vector) axes. 1023 final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez); 1024 final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE; 1025 final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE; 1026 if (I.length == 9) { 1027 I[0] = 1; I[1] = 0; I[2] = 0; 1028 I[3] = 0; I[4] = c; I[5] = s; 1029 I[6] = 0; I[7] =-s; I[8] = c; 1030 } else if (I.length == 16) { 1031 I[0] = 1; I[1] = 0; I[2] = 0; 1032 I[4] = 0; I[5] = c; I[6] = s; 1033 I[8] = 0; I[9] =-s; I[10]= c; 1034 I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0; 1035 I[15] = 1; 1036 } 1037 } 1038 return true; 1039 } 1040 1041 /** 1042 * Computes the geomagnetic inclination angle in radians from the 1043 * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}. 1044 * 1045 * @param I 1046 * inclination matrix see {@link #getRotationMatrix}. 1047 * 1048 * @return The geomagnetic inclination angle in radians. 1049 * 1050 * @see #getRotationMatrix(float[], float[], float[], float[]) 1051 * @see #getOrientation(float[], float[]) 1052 * @see GeomagneticField 1053 * 1054 */ 1055 public static float getInclination(float[] I) { 1056 if (I.length == 9) { 1057 return (float)Math.atan2(I[5], I[4]); 1058 } else { 1059 return (float)Math.atan2(I[6], I[5]); 1060 } 1061 } 1062 1063 /** 1064 * <p> 1065 * Rotates the supplied rotation matrix so it is expressed in a different 1066 * coordinate system. This is typically used when an application needs to 1067 * compute the three orientation angles of the device (see 1068 * {@link #getOrientation}) in a different coordinate system. 1069 * </p> 1070 * 1071 * <p> 1072 * When the rotation matrix is used for drawing (for instance with OpenGL 1073 * ES), it usually <b>doesn't need</b> to be transformed by this function, 1074 * unless the screen is physically rotated, in which case you can use 1075 * {@link android.view.Display#getRotation() Display.getRotation()} to 1076 * retrieve the current rotation of the screen. Note that because the user 1077 * is generally free to rotate their screen, you often should consider the 1078 * rotation in deciding the parameters to use here. 1079 * </p> 1080 * 1081 * <p> 1082 * <u>Examples:</u> 1083 * <p> 1084 * 1085 * <ul> 1086 * <li>Using the camera (Y axis along the camera's axis) for an augmented 1087 * reality application where the rotation angles are needed:</li> 1088 * 1089 * <p> 1090 * <ul> 1091 * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code> 1092 * </ul> 1093 * </p> 1094 * 1095 * <li>Using the device as a mechanical compass when rotation is 1096 * {@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:</li> 1097 * 1098 * <p> 1099 * <ul> 1100 * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code> 1101 * </ul> 1102 * </p> 1103 * 1104 * Beware of the above example. This call is needed only to account for a 1105 * rotation from its natural orientation when calculating the rotation 1106 * angles (see {@link #getOrientation}). If the rotation matrix is also used 1107 * for rendering, it may not need to be transformed, for instance if your 1108 * {@link android.app.Activity Activity} is running in landscape mode. 1109 * </ul> 1110 * 1111 * <p> 1112 * Since the resulting coordinate system is orthonormal, only two axes need 1113 * to be specified. 1114 * 1115 * @param inR 1116 * the rotation matrix to be transformed. Usually it is the matrix 1117 * returned by {@link #getRotationMatrix}. 1118 * 1119 * @param X 1120 * defines on which world axis and direction the X axis of the device 1121 * is mapped. 1122 * 1123 * @param Y 1124 * defines on which world axis and direction the Y axis of the device 1125 * is mapped. 1126 * 1127 * @param outR 1128 * the transformed rotation matrix. inR and outR should not be the same 1129 * array. 1130 * 1131 * @return <code>true</code> on success. <code>false</code> if the input 1132 * parameters are incorrect, for instance if X and Y define the same 1133 * axis. Or if inR and outR don't have the same length. 1134 * 1135 * @see #getRotationMatrix(float[], float[], float[], float[]) 1136 */ 1137 1138 public static boolean remapCoordinateSystem(float[] inR, int X, int Y, 1139 float[] outR) 1140 { 1141 if (inR == outR) { 1142 final float[] temp = mTempMatrix; 1143 synchronized(temp) { 1144 // we don't expect to have a lot of contention 1145 if (remapCoordinateSystemImpl(inR, X, Y, temp)) { 1146 final int size = outR.length; 1147 for (int i=0 ; i<size ; i++) 1148 outR[i] = temp[i]; 1149 return true; 1150 } 1151 } 1152 } 1153 return remapCoordinateSystemImpl(inR, X, Y, outR); 1154 } 1155 1156 private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y, 1157 float[] outR) 1158 { 1159 /* 1160 * X and Y define a rotation matrix 'r': 1161 * 1162 * (X==1)?((X&0x80)?-1:1):0 (X==2)?((X&0x80)?-1:1):0 (X==3)?((X&0x80)?-1:1):0 1163 * (Y==1)?((Y&0x80)?-1:1):0 (Y==2)?((Y&0x80)?-1:1):0 (Y==3)?((X&0x80)?-1:1):0 1164 * r[0] ^ r[1] 1165 * 1166 * where the 3rd line is the vector product of the first 2 lines 1167 * 1168 */ 1169 1170 final int length = outR.length; 1171 if (inR.length != length) 1172 return false; // invalid parameter 1173 if ((X & 0x7C)!=0 || (Y & 0x7C)!=0) 1174 return false; // invalid parameter 1175 if (((X & 0x3)==0) || ((Y & 0x3)==0)) 1176 return false; // no axis specified 1177 if ((X & 0x3) == (Y & 0x3)) 1178 return false; // same axis specified 1179 1180 // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y) 1181 // this can be calculated by exclusive-or'ing X and Y; except for 1182 // the sign inversion (+/-) which is calculated below. 1183 int Z = X ^ Y; 1184 1185 // extract the axis (remove the sign), offset in the range 0 to 2. 1186 final int x = (X & 0x3)-1; 1187 final int y = (Y & 0x3)-1; 1188 final int z = (Z & 0x3)-1; 1189 1190 // compute the sign of Z (whether it needs to be inverted) 1191 final int axis_y = (z+1)%3; 1192 final int axis_z = (z+2)%3; 1193 if (((x^axis_y)|(y^axis_z)) != 0) 1194 Z ^= 0x80; 1195 1196 final boolean sx = (X>=0x80); 1197 final boolean sy = (Y>=0x80); 1198 final boolean sz = (Z>=0x80); 1199 1200 // Perform R * r, in avoiding actual muls and adds. 1201 final int rowLength = ((length==16)?4:3); 1202 for (int j=0 ; j<3 ; j++) { 1203 final int offset = j*rowLength; 1204 for (int i=0 ; i<3 ; i++) { 1205 if (x==i) outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0]; 1206 if (y==i) outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1]; 1207 if (z==i) outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2]; 1208 } 1209 } 1210 if (length == 16) { 1211 outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0; 1212 outR[15] = 1; 1213 } 1214 return true; 1215 } 1216 1217 /** 1218 * Computes the device's orientation based on the rotation matrix. 1219 * <p> 1220 * When it returns, the array values is filled with the result: 1221 * <ul> 1222 * <li>values[0]: <i>azimuth</i>, rotation around the Z axis.</li> 1223 * <li>values[1]: <i>pitch</i>, rotation around the X axis.</li> 1224 * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li> 1225 * </ul> 1226 * <p>The reference coordinate-system used is different from the world 1227 * coordinate-system defined for the rotation matrix:</p> 1228 * <ul> 1229 * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to 1230 * the ground at the device's current location and roughly points West).</li> 1231 * <li>Y is tangential to the ground at the device's current location and 1232 * points towards the magnetic North Pole.</li> 1233 * <li>Z points towards the center of the Earth and is perpendicular to the ground.</li> 1234 * </ul> 1235 * 1236 * <p> 1237 * <center><img src="../../../images/axis_globe_inverted.png" 1238 * alt="Inverted world coordinate-system diagram." border="0" /></center> 1239 * </p> 1240 * <p> 1241 * All three angles above are in <b>radians</b> and <b>positive</b> in the 1242 * <b>counter-clockwise</b> direction. 1243 * 1244 * @param R 1245 * rotation matrix see {@link #getRotationMatrix}. 1246 * 1247 * @param values 1248 * an array of 3 floats to hold the result. 1249 * 1250 * @return The array values passed as argument. 1251 * 1252 * @see #getRotationMatrix(float[], float[], float[], float[]) 1253 * @see GeomagneticField 1254 */ 1255 public static float[] getOrientation(float[] R, float values[]) { 1256 /* 1257 * 4x4 (length=16) case: 1258 * / R[ 0] R[ 1] R[ 2] 0 \ 1259 * | R[ 4] R[ 5] R[ 6] 0 | 1260 * | R[ 8] R[ 9] R[10] 0 | 1261 * \ 0 0 0 1 / 1262 * 1263 * 3x3 (length=9) case: 1264 * / R[ 0] R[ 1] R[ 2] \ 1265 * | R[ 3] R[ 4] R[ 5] | 1266 * \ R[ 6] R[ 7] R[ 8] / 1267 * 1268 */ 1269 if (R.length == 9) { 1270 values[0] = (float)Math.atan2(R[1], R[4]); 1271 values[1] = (float)Math.asin(-R[7]); 1272 values[2] = (float)Math.atan2(-R[6], R[8]); 1273 } else { 1274 values[0] = (float)Math.atan2(R[1], R[5]); 1275 values[1] = (float)Math.asin(-R[9]); 1276 values[2] = (float)Math.atan2(-R[8], R[10]); 1277 } 1278 return values; 1279 } 1280 1281 /** 1282 * Computes the Altitude in meters from the atmospheric pressure and the 1283 * pressure at sea level. 1284 * <p> 1285 * Typically the atmospheric pressure is read from a 1286 * {@link Sensor#TYPE_PRESSURE} sensor. The pressure at sea level must be 1287 * known, usually it can be retrieved from airport databases in the 1288 * vicinity. If unknown, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE} 1289 * as an approximation, but absolute altitudes won't be accurate. 1290 * </p> 1291 * <p> 1292 * To calculate altitude differences, you must calculate the difference 1293 * between the altitudes at both points. If you don't know the altitude 1294 * as sea level, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE} instead, 1295 * which will give good results considering the range of pressure typically 1296 * involved. 1297 * </p> 1298 * <p> 1299 * <code><ul> 1300 * float altitude_difference = 1301 * getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point2) 1302 * - getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point1); 1303 * </ul></code> 1304 * </p> 1305 * 1306 * @param p0 pressure at sea level 1307 * @param p atmospheric pressure 1308 * @return Altitude in meters 1309 */ 1310 public static float getAltitude(float p0, float p) { 1311 final float coef = 1.0f / 5.255f; 1312 return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef)); 1313 } 1314 1315 /** Helper function to compute the angle change between two rotation matrices. 1316 * Given a current rotation matrix (R) and a previous rotation matrix 1317 * (prevR) computes the rotation around the z,x, and y axes which 1318 * transforms prevR to R. 1319 * outputs a 3 element vector containing the z,x, and y angle 1320 * change at indexes 0, 1, and 2 respectively. 1321 * <p> Each input matrix is either as a 3x3 or 4x4 row-major matrix 1322 * depending on the length of the passed array: 1323 * <p>If the array length is 9, then the array elements represent this matrix 1324 * <pre> 1325 * / R[ 0] R[ 1] R[ 2] \ 1326 * | R[ 3] R[ 4] R[ 5] | 1327 * \ R[ 6] R[ 7] R[ 8] / 1328 *</pre> 1329 * <p>If the array length is 16, then the array elements represent this matrix 1330 * <pre> 1331 * / R[ 0] R[ 1] R[ 2] R[ 3] \ 1332 * | R[ 4] R[ 5] R[ 6] R[ 7] | 1333 * | R[ 8] R[ 9] R[10] R[11] | 1334 * \ R[12] R[13] R[14] R[15] / 1335 *</pre> 1336 * @param R current rotation matrix 1337 * @param prevR previous rotation matrix 1338 * @param angleChange an an array of floats (z, x, and y) in which the angle change is stored 1339 */ 1340 1341 public static void getAngleChange( float[] angleChange, float[] R, float[] prevR) { 1342 float rd1=0,rd4=0, rd6=0,rd7=0, rd8=0; 1343 float ri0=0,ri1=0,ri2=0,ri3=0,ri4=0,ri5=0,ri6=0,ri7=0,ri8=0; 1344 float pri0=0, pri1=0, pri2=0, pri3=0, pri4=0, pri5=0, pri6=0, pri7=0, pri8=0; 1345 1346 if(R.length == 9) { 1347 ri0 = R[0]; 1348 ri1 = R[1]; 1349 ri2 = R[2]; 1350 ri3 = R[3]; 1351 ri4 = R[4]; 1352 ri5 = R[5]; 1353 ri6 = R[6]; 1354 ri7 = R[7]; 1355 ri8 = R[8]; 1356 } else if(R.length == 16) { 1357 ri0 = R[0]; 1358 ri1 = R[1]; 1359 ri2 = R[2]; 1360 ri3 = R[4]; 1361 ri4 = R[5]; 1362 ri5 = R[6]; 1363 ri6 = R[8]; 1364 ri7 = R[9]; 1365 ri8 = R[10]; 1366 } 1367 1368 if(prevR.length == 9) { 1369 pri0 = prevR[0]; 1370 pri1 = prevR[1]; 1371 pri2 = prevR[2]; 1372 pri3 = prevR[3]; 1373 pri4 = prevR[4]; 1374 pri5 = prevR[5]; 1375 pri6 = prevR[6]; 1376 pri7 = prevR[7]; 1377 pri8 = prevR[8]; 1378 } else if(prevR.length == 16) { 1379 pri0 = prevR[0]; 1380 pri1 = prevR[1]; 1381 pri2 = prevR[2]; 1382 pri3 = prevR[4]; 1383 pri4 = prevR[5]; 1384 pri5 = prevR[6]; 1385 pri6 = prevR[8]; 1386 pri7 = prevR[9]; 1387 pri8 = prevR[10]; 1388 } 1389 1390 // calculate the parts of the rotation difference matrix we need 1391 // rd[i][j] = pri[0][i] * ri[0][j] + pri[1][i] * ri[1][j] + pri[2][i] * ri[2][j]; 1392 1393 rd1 = pri0 * ri1 + pri3 * ri4 + pri6 * ri7; //rd[0][1] 1394 rd4 = pri1 * ri1 + pri4 * ri4 + pri7 * ri7; //rd[1][1] 1395 rd6 = pri2 * ri0 + pri5 * ri3 + pri8 * ri6; //rd[2][0] 1396 rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1] 1397 rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2] 1398 1399 angleChange[0] = (float)Math.atan2(rd1, rd4); 1400 angleChange[1] = (float)Math.asin(-rd7); 1401 angleChange[2] = (float)Math.atan2(-rd6, rd8); 1402 1403 } 1404 1405 /** Helper function to convert a rotation vector to a rotation matrix. 1406 * Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a 1407 * 9 or 16 element rotation matrix in the array R. R must have length 9 or 16. 1408 * If R.length == 9, the following matrix is returned: 1409 * <pre> 1410 * / R[ 0] R[ 1] R[ 2] \ 1411 * | R[ 3] R[ 4] R[ 5] | 1412 * \ R[ 6] R[ 7] R[ 8] / 1413 *</pre> 1414 * If R.length == 16, the following matrix is returned: 1415 * <pre> 1416 * / R[ 0] R[ 1] R[ 2] 0 \ 1417 * | R[ 4] R[ 5] R[ 6] 0 | 1418 * | R[ 8] R[ 9] R[10] 0 | 1419 * \ 0 0 0 1 / 1420 *</pre> 1421 * @param rotationVector the rotation vector to convert 1422 * @param R an array of floats in which to store the rotation matrix 1423 */ 1424 public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) { 1425 1426 float q0; 1427 float q1 = rotationVector[0]; 1428 float q2 = rotationVector[1]; 1429 float q3 = rotationVector[2]; 1430 1431 if (rotationVector.length >= 4) { 1432 q0 = rotationVector[3]; 1433 } else { 1434 q0 = 1 - q1*q1 - q2*q2 - q3*q3; 1435 q0 = (q0 > 0) ? (float)Math.sqrt(q0) : 0; 1436 } 1437 1438 float sq_q1 = 2 * q1 * q1; 1439 float sq_q2 = 2 * q2 * q2; 1440 float sq_q3 = 2 * q3 * q3; 1441 float q1_q2 = 2 * q1 * q2; 1442 float q3_q0 = 2 * q3 * q0; 1443 float q1_q3 = 2 * q1 * q3; 1444 float q2_q0 = 2 * q2 * q0; 1445 float q2_q3 = 2 * q2 * q3; 1446 float q1_q0 = 2 * q1 * q0; 1447 1448 if(R.length == 9) { 1449 R[0] = 1 - sq_q2 - sq_q3; 1450 R[1] = q1_q2 - q3_q0; 1451 R[2] = q1_q3 + q2_q0; 1452 1453 R[3] = q1_q2 + q3_q0; 1454 R[4] = 1 - sq_q1 - sq_q3; 1455 R[5] = q2_q3 - q1_q0; 1456 1457 R[6] = q1_q3 - q2_q0; 1458 R[7] = q2_q3 + q1_q0; 1459 R[8] = 1 - sq_q1 - sq_q2; 1460 } else if (R.length == 16) { 1461 R[0] = 1 - sq_q2 - sq_q3; 1462 R[1] = q1_q2 - q3_q0; 1463 R[2] = q1_q3 + q2_q0; 1464 R[3] = 0.0f; 1465 1466 R[4] = q1_q2 + q3_q0; 1467 R[5] = 1 - sq_q1 - sq_q3; 1468 R[6] = q2_q3 - q1_q0; 1469 R[7] = 0.0f; 1470 1471 R[8] = q1_q3 - q2_q0; 1472 R[9] = q2_q3 + q1_q0; 1473 R[10] = 1 - sq_q1 - sq_q2; 1474 R[11] = 0.0f; 1475 1476 R[12] = R[13] = R[14] = 0.0f; 1477 R[15] = 1.0f; 1478 } 1479 } 1480 1481 /** Helper function to convert a rotation vector to a normalized quaternion. 1482 * Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a normalized 1483 * quaternion in the array Q. The quaternion is stored as [w, x, y, z] 1484 * @param rv the rotation vector to convert 1485 * @param Q an array of floats in which to store the computed quaternion 1486 */ 1487 public static void getQuaternionFromVector(float[] Q, float[] rv) { 1488 if (rv.length >= 4) { 1489 Q[0] = rv[3]; 1490 } else { 1491 Q[0] = 1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2]; 1492 Q[0] = (Q[0] > 0) ? (float)Math.sqrt(Q[0]) : 0; 1493 } 1494 Q[1] = rv[0]; 1495 Q[2] = rv[1]; 1496 Q[3] = rv[2]; 1497 } 1498 1499 /** 1500 * Requests receiving trigger events for a trigger sensor. 1501 * 1502 * <p> 1503 * When the sensor detects a trigger event condition, such as significant motion in 1504 * the case of the {@link Sensor#TYPE_SIGNIFICANT_MOTION}, the provided trigger listener 1505 * will be invoked once and then its request to receive trigger events will be canceled. 1506 * To continue receiving trigger events, the application must request to receive trigger 1507 * events again. 1508 * </p> 1509 * 1510 * @param listener The listener on which the 1511 * {@link TriggerEventListener#onTrigger(TriggerEvent)} will be delivered. 1512 * @param sensor The sensor to be enabled. 1513 * 1514 * @return true if the sensor was successfully enabled. 1515 * 1516 * @throws IllegalArgumentException when sensor is null or not a trigger sensor. 1517 */ 1518 public boolean requestTriggerSensor(TriggerEventListener listener, Sensor sensor) { 1519 return requestTriggerSensorImpl(listener, sensor); 1520 } 1521 1522 /** 1523 * @hide 1524 */ 1525 protected abstract boolean requestTriggerSensorImpl(TriggerEventListener listener, 1526 Sensor sensor); 1527 1528 /** 1529 * Cancels receiving trigger events for a trigger sensor. 1530 * 1531 * <p> 1532 * Note that a Trigger sensor will be auto disabled if 1533 * {@link TriggerEventListener#onTrigger(TriggerEvent)} has triggered. 1534 * This method is provided in case the user wants to explicitly cancel the request 1535 * to receive trigger events. 1536 * </p> 1537 * 1538 * @param listener The listener on which the 1539 * {@link TriggerEventListener#onTrigger(TriggerEvent)} 1540 * is delivered.It should be the same as the one used 1541 * in {@link #requestTriggerSensor(TriggerEventListener, Sensor)} 1542 * @param sensor The sensor for which the trigger request should be canceled. 1543 * If null, it cancels receiving trigger for all sensors associated 1544 * with the listener. 1545 * 1546 * @return true if successfully canceled. 1547 * 1548 * @throws IllegalArgumentException when sensor is a trigger sensor. 1549 */ 1550 public boolean cancelTriggerSensor(TriggerEventListener listener, Sensor sensor) { 1551 return cancelTriggerSensorImpl(listener, sensor, true); 1552 } 1553 1554 /** 1555 * @hide 1556 */ 1557 protected abstract boolean cancelTriggerSensorImpl(TriggerEventListener listener, 1558 Sensor sensor, boolean disable); 1559 1560 1561 /** 1562 * For testing purposes only. Not for third party applications. 1563 * 1564 * Enable data injection mode in sensor service. This mode is 1565 * expected to be used only for testing purposes. If the HAL is 1566 * set to data injection mode, it will ignore the input from 1567 * physical sensors and read sensor data that is injected from 1568 * the test application. This mode is used for testing vendor 1569 * implementations for various algorithms like Rotation Vector, 1570 * Significant Motion, Step Counter etc. 1571 * 1572 * The tests which call this API need to have {@code 1573 * android.permission.HARDWARE_TEST} permission which isn't 1574 * available for third party applications. 1575 * 1576 * @param enable True to set the HAL in DATA_INJECTION mode. 1577 * False to reset the HAL back to NORMAL mode. 1578 * 1579 * @return true if the HAL supports data injection and false 1580 * otherwise. 1581 * @hide 1582 */ 1583 @SystemApi 1584 public boolean enableDataInjectionMode(boolean enable) { 1585 return enableDataInjectionImpl(enable); 1586 } 1587 1588 /** 1589 * @hide 1590 */ 1591 protected abstract boolean enableDataInjectionImpl(boolean enable); 1592 1593 /** 1594 * For testing purposes only. Not for third party applications. 1595 * 1596 * This method is used to inject raw sensor data into the HAL. 1597 * Call enableDataInjection before this method to set the HAL in 1598 * data injection mode. This method should be called only if a 1599 * previous call to enableDataInjection has been successful and 1600 * the HAL is already in data injection mode. 1601 * 1602 * The tests which call this API need to have {@code 1603 * android.permission.HARDWARE_TEST} permission which isn't 1604 * available for third party applications. 1605 * 1606 * @param sensor The sensor to inject. 1607 * @param values Sensor values to inject. The length of this 1608 * array must be exactly equal to the number of 1609 * values reported by the sensor type. 1610 * @param accuracy Accuracy of the sensor. 1611 * @param timestamp Sensor timestamp associated with the event. 1612 * 1613 * @return boolean True if the data injection succeeds, false 1614 * otherwise. 1615 * @throws IllegalArgumentException when the sensor is null, 1616 * data injection is not supported by the sensor, values 1617 * are null, incorrect number of values for the sensor, 1618 * sensor accuracy is incorrect or timestamps are 1619 * invalid. 1620 * @hide 1621 */ 1622 @SystemApi 1623 public boolean injectSensorData(Sensor sensor, float[] values, int accuracy, 1624 long timestamp) { 1625 if (sensor == null) { 1626 throw new IllegalArgumentException("sensor cannot be null"); 1627 } 1628 if (!sensor.isDataInjectionSupported()) { 1629 throw new IllegalArgumentException("sensor does not support data injection"); 1630 } 1631 if (values == null) { 1632 throw new IllegalArgumentException("sensor data cannot be null"); 1633 } 1634 int expectedNumValues = Sensor.getMaxLengthValuesArray(sensor, Build.VERSION_CODES.MNC); 1635 if (values.length != expectedNumValues) { 1636 throw new IllegalArgumentException ("Wrong number of values for sensor " + 1637 sensor.getName() + " actual=" + values.length + " expected=" + 1638 expectedNumValues); 1639 } 1640 if (accuracy < SENSOR_STATUS_NO_CONTACT || accuracy > SENSOR_STATUS_ACCURACY_HIGH) { 1641 throw new IllegalArgumentException("Invalid sensor accuracy"); 1642 } 1643 if (timestamp <= 0) { 1644 throw new IllegalArgumentException("Negative or zero sensor timestamp"); 1645 } 1646 if (timestamp > SystemClock.elapsedRealtimeNanos()) { 1647 throw new IllegalArgumentException("Sensor timestamp into the future"); 1648 } 1649 return injectSensorDataImpl(sensor, values, accuracy, timestamp); 1650 } 1651 1652 /** 1653 * @hide 1654 */ 1655 protected abstract boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy, 1656 long timestamp); 1657 1658 private LegacySensorManager getLegacySensorManager() { 1659 synchronized (mSensorListByType) { 1660 if (mLegacySensorManager == null) { 1661 Log.i(TAG, "This application is using deprecated SensorManager API which will " 1662 + "be removed someday. Please consider switching to the new API."); 1663 mLegacySensorManager = new LegacySensorManager(this); 1664 } 1665 return mLegacySensorManager; 1666 } 1667 } 1668 1669 private static int getDelay(int rate) { 1670 int delay = -1; 1671 switch (rate) { 1672 case SENSOR_DELAY_FASTEST: 1673 delay = 0; 1674 break; 1675 case SENSOR_DELAY_GAME: 1676 delay = 20000; 1677 break; 1678 case SENSOR_DELAY_UI: 1679 delay = 66667; 1680 break; 1681 case SENSOR_DELAY_NORMAL: 1682 delay = 200000; 1683 break; 1684 default: 1685 delay = rate; 1686 break; 1687 } 1688 return delay; 1689 } 1690} 1691