1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.hardware; 18 19 import android.annotation.SystemApi; 20 import android.annotation.SystemService; 21 import android.compat.annotation.UnsupportedAppUsage; 22 import android.content.Context; 23 import android.os.Build; 24 import android.os.Handler; 25 import android.os.MemoryFile; 26 import android.util.Log; 27 import android.util.SparseArray; 28 29 import java.util.ArrayList; 30 import java.util.Collections; 31 import java.util.List; 32 33 /** 34 * <p> 35 * SensorManager lets you access the device's {@link android.hardware.Sensor 36 * sensors}. 37 * </p> 38 * <p> 39 * Always make sure to disable sensors you don't need, especially when your 40 * activity is paused. Failing to do so can drain the battery in just a few 41 * hours. Note that the system will <i>not</i> disable sensors automatically when 42 * the screen turns off. 43 * </p> 44 * <p class="note"> 45 * Note: Don't use this mechanism with a Trigger Sensor, have a look 46 * at {@link TriggerEventListener}. {@link Sensor#TYPE_SIGNIFICANT_MOTION} 47 * is an example of a trigger sensor. 48 * </p> 49 * <pre class="prettyprint"> 50 * public class SensorActivity extends Activity implements SensorEventListener { 51 * private final SensorManager mSensorManager; 52 * private final Sensor mAccelerometer; 53 * 54 * public SensorActivity() { 55 * mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE); 56 * mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 57 * } 58 * 59 * protected void onResume() { 60 * super.onResume(); 61 * mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); 62 * } 63 * 64 * protected void onPause() { 65 * super.onPause(); 66 * mSensorManager.unregisterListener(this); 67 * } 68 * 69 * public void onAccuracyChanged(Sensor sensor, int accuracy) { 70 * } 71 * 72 * public void onSensorChanged(SensorEvent event) { 73 * } 74 * } 75 * </pre> 76 * 77 * @see SensorEventListener 78 * @see SensorEvent 79 * @see Sensor 80 * 81 */ 82 @SystemService(Context.SENSOR_SERVICE) 83 public abstract class SensorManager { 84 /** @hide */ 85 protected static final String TAG = "SensorManager"; 86 87 private static final float[] sTempMatrix = new float[16]; 88 89 // Cached lists of sensors by type. Guarded by mSensorListByType. 90 private final SparseArray<List<Sensor>> mSensorListByType = 91 new SparseArray<List<Sensor>>(); 92 93 // Legacy sensor manager implementation. Guarded by mSensorListByType during initialization. 94 private LegacySensorManager mLegacySensorManager; 95 96 /* NOTE: sensor IDs must be a power of 2 */ 97 98 /** 99 * A constant describing an orientation sensor. See 100 * {@link android.hardware.SensorListener SensorListener} for more details. 101 * 102 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 103 */ 104 @Deprecated 105 public static final int SENSOR_ORIENTATION = 1 << 0; 106 107 /** 108 * A constant describing an accelerometer. See 109 * {@link android.hardware.SensorListener SensorListener} for more details. 110 * 111 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 112 */ 113 @Deprecated 114 public static final int SENSOR_ACCELEROMETER = 1 << 1; 115 116 /** 117 * A constant describing a temperature sensor See 118 * {@link android.hardware.SensorListener SensorListener} for more details. 119 * 120 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 121 */ 122 @Deprecated 123 public static final int SENSOR_TEMPERATURE = 1 << 2; 124 125 /** 126 * A constant describing a magnetic sensor See 127 * {@link android.hardware.SensorListener SensorListener} for more details. 128 * 129 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 130 */ 131 @Deprecated 132 public static final int SENSOR_MAGNETIC_FIELD = 1 << 3; 133 134 /** 135 * A constant describing an ambient light sensor See 136 * {@link android.hardware.SensorListener SensorListener} for more details. 137 * 138 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 139 */ 140 @Deprecated 141 public static final int SENSOR_LIGHT = 1 << 4; 142 143 /** 144 * A constant describing a proximity sensor See 145 * {@link android.hardware.SensorListener SensorListener} for more details. 146 * 147 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 148 */ 149 @Deprecated 150 public static final int SENSOR_PROXIMITY = 1 << 5; 151 152 /** 153 * A constant describing a Tricorder See 154 * {@link android.hardware.SensorListener SensorListener} for more details. 155 * 156 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 157 */ 158 @Deprecated 159 public static final int SENSOR_TRICORDER = 1 << 6; 160 161 /** 162 * A constant describing an orientation sensor. See 163 * {@link android.hardware.SensorListener SensorListener} for more details. 164 * 165 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 166 */ 167 @Deprecated 168 public static final int SENSOR_ORIENTATION_RAW = 1 << 7; 169 170 /** 171 * A constant that includes all sensors 172 * 173 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 174 */ 175 @Deprecated 176 public static final int SENSOR_ALL = 0x7F; 177 178 /** 179 * Smallest sensor ID 180 * 181 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 182 */ 183 @Deprecated 184 public static final int SENSOR_MIN = SENSOR_ORIENTATION; 185 186 /** 187 * Largest sensor ID 188 * 189 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 190 */ 191 @Deprecated 192 public static final int SENSOR_MAX = ((SENSOR_ALL + 1) >> 1); 193 194 195 /** 196 * Index of the X value in the array returned by 197 * {@link android.hardware.SensorListener#onSensorChanged} 198 * 199 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 200 */ 201 @Deprecated 202 public static final int DATA_X = 0; 203 204 /** 205 * Index of the Y value in the array returned by 206 * {@link android.hardware.SensorListener#onSensorChanged} 207 * 208 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 209 */ 210 @Deprecated 211 public static final int DATA_Y = 1; 212 213 /** 214 * Index of the Z value in the array returned by 215 * {@link android.hardware.SensorListener#onSensorChanged} 216 * 217 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 218 */ 219 @Deprecated 220 public static final int DATA_Z = 2; 221 222 /** 223 * Offset to the untransformed values in the array returned by 224 * {@link android.hardware.SensorListener#onSensorChanged} 225 * 226 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 227 */ 228 @Deprecated 229 public static final int RAW_DATA_INDEX = 3; 230 231 /** 232 * Index of the untransformed X value in the array returned by 233 * {@link android.hardware.SensorListener#onSensorChanged} 234 * 235 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 236 */ 237 @Deprecated 238 public static final int RAW_DATA_X = 3; 239 240 /** 241 * Index of the untransformed Y value in the array returned by 242 * {@link android.hardware.SensorListener#onSensorChanged} 243 * 244 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 245 */ 246 @Deprecated 247 public static final int RAW_DATA_Y = 4; 248 249 /** 250 * Index of the untransformed Z value in the array returned by 251 * {@link android.hardware.SensorListener#onSensorChanged} 252 * 253 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 254 */ 255 @Deprecated 256 public static final int RAW_DATA_Z = 5; 257 258 /** Standard gravity (g) on Earth. This value is equivalent to 1G */ 259 public static final float STANDARD_GRAVITY = 9.80665f; 260 261 /** Sun's gravity in SI units (m/s^2) */ 262 public static final float GRAVITY_SUN = 275.0f; 263 /** Mercury's gravity in SI units (m/s^2) */ 264 public static final float GRAVITY_MERCURY = 3.70f; 265 /** Venus' gravity in SI units (m/s^2) */ 266 public static final float GRAVITY_VENUS = 8.87f; 267 /** Earth's gravity in SI units (m/s^2) */ 268 public static final float GRAVITY_EARTH = 9.80665f; 269 /** The Moon's gravity in SI units (m/s^2) */ 270 public static final float GRAVITY_MOON = 1.6f; 271 /** Mars' gravity in SI units (m/s^2) */ 272 public static final float GRAVITY_MARS = 3.71f; 273 /** Jupiter's gravity in SI units (m/s^2) */ 274 public static final float GRAVITY_JUPITER = 23.12f; 275 /** Saturn's gravity in SI units (m/s^2) */ 276 public static final float GRAVITY_SATURN = 8.96f; 277 /** Uranus' gravity in SI units (m/s^2) */ 278 public static final float GRAVITY_URANUS = 8.69f; 279 /** Neptune's gravity in SI units (m/s^2) */ 280 public static final float GRAVITY_NEPTUNE = 11.0f; 281 /** Pluto's gravity in SI units (m/s^2) */ 282 public static final float GRAVITY_PLUTO = 0.6f; 283 /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */ 284 public static final float GRAVITY_DEATH_STAR_I = 0.000000353036145f; 285 /** Gravity on the island */ 286 public static final float GRAVITY_THE_ISLAND = 4.815162342f; 287 288 289 /** Maximum magnetic field on Earth's surface */ 290 public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f; 291 /** Minimum magnetic field on Earth's surface */ 292 public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f; 293 294 295 /** Standard atmosphere, or average sea-level pressure in hPa (millibar) */ 296 public static final float PRESSURE_STANDARD_ATMOSPHERE = 1013.25f; 297 298 299 /** Maximum luminance of sunlight in lux */ 300 public static final float LIGHT_SUNLIGHT_MAX = 120000.0f; 301 /** luminance of sunlight in lux */ 302 public static final float LIGHT_SUNLIGHT = 110000.0f; 303 /** luminance in shade in lux */ 304 public static final float LIGHT_SHADE = 20000.0f; 305 /** luminance under an overcast sky in lux */ 306 public static final float LIGHT_OVERCAST = 10000.0f; 307 /** luminance at sunrise in lux */ 308 public static final float LIGHT_SUNRISE = 400.0f; 309 /** luminance under a cloudy sky in lux */ 310 public static final float LIGHT_CLOUDY = 100.0f; 311 /** luminance at night with full moon in lux */ 312 public static final float LIGHT_FULLMOON = 0.25f; 313 /** luminance at night with no moon in lux*/ 314 public static final float LIGHT_NO_MOON = 0.001f; 315 316 317 /** get sensor data as fast as possible */ 318 public static final int SENSOR_DELAY_FASTEST = 0; 319 /** rate suitable for games */ 320 public static final int SENSOR_DELAY_GAME = 1; 321 /** rate suitable for the user interface */ 322 public static final int SENSOR_DELAY_UI = 2; 323 /** rate (default) suitable for screen orientation changes */ 324 public static final int SENSOR_DELAY_NORMAL = 3; 325 326 327 /** 328 * The values returned by this sensor cannot be trusted because the sensor 329 * had no contact with what it was measuring (for example, the heart rate 330 * monitor is not in contact with the user). 331 */ 332 public static final int SENSOR_STATUS_NO_CONTACT = -1; 333 334 /** 335 * The values returned by this sensor cannot be trusted, calibration is 336 * needed or the environment doesn't allow readings 337 */ 338 public static final int SENSOR_STATUS_UNRELIABLE = 0; 339 340 /** 341 * This sensor is reporting data with low accuracy, calibration with the 342 * environment is needed 343 */ 344 public static final int SENSOR_STATUS_ACCURACY_LOW = 1; 345 346 /** 347 * This sensor is reporting data with an average level of accuracy, 348 * calibration with the environment may improve the readings 349 */ 350 public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2; 351 352 /** This sensor is reporting data with maximum accuracy */ 353 public static final int SENSOR_STATUS_ACCURACY_HIGH = 3; 354 355 /** see {@link #remapCoordinateSystem} */ 356 public static final int AXIS_X = 1; 357 /** see {@link #remapCoordinateSystem} */ 358 public static final int AXIS_Y = 2; 359 /** see {@link #remapCoordinateSystem} */ 360 public static final int AXIS_Z = 3; 361 /** see {@link #remapCoordinateSystem} */ 362 public static final int AXIS_MINUS_X = AXIS_X | 0x80; 363 /** see {@link #remapCoordinateSystem} */ 364 public static final int AXIS_MINUS_Y = AXIS_Y | 0x80; 365 /** see {@link #remapCoordinateSystem} */ 366 public static final int AXIS_MINUS_Z = AXIS_Z | 0x80; 367 368 369 /** 370 * {@hide} 371 */ 372 @UnsupportedAppUsage SensorManager()373 public SensorManager() { 374 } 375 376 /** 377 * Gets the full list of sensors that are available. 378 * @hide 379 */ getFullSensorList()380 protected abstract List<Sensor> getFullSensorList(); 381 382 /** 383 * Gets the full list of dynamic sensors that are available. 384 * @hide 385 */ getFullDynamicSensorList()386 protected abstract List<Sensor> getFullDynamicSensorList(); 387 388 /** 389 * @return available sensors. 390 * @deprecated This method is deprecated, use 391 * {@link SensorManager#getSensorList(int)} instead 392 */ 393 @Deprecated getSensors()394 public int getSensors() { 395 return getLegacySensorManager().getSensors(); 396 } 397 398 /** 399 * Use this method to get the list of available sensors of a certain type. 400 * Make multiple calls to get sensors of different types or use 401 * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the 402 * sensors. 403 * 404 * <p class="note"> 405 * NOTE: Both wake-up and non wake-up sensors matching the given type are 406 * returned. Check {@link Sensor#isWakeUpSensor()} to know the wake-up properties 407 * of the returned {@link Sensor}. 408 * </p> 409 * 410 * @param type 411 * of sensors requested 412 * 413 * @return a list of sensors matching the asked type. 414 * 415 * @see #getDefaultSensor(int) 416 * @see Sensor 417 */ getSensorList(int type)418 public List<Sensor> getSensorList(int type) { 419 // cache the returned lists the first time 420 List<Sensor> list; 421 final List<Sensor> fullList = getFullSensorList(); 422 synchronized (mSensorListByType) { 423 list = mSensorListByType.get(type); 424 if (list == null) { 425 if (type == Sensor.TYPE_ALL) { 426 list = fullList; 427 } else { 428 list = new ArrayList<Sensor>(); 429 for (Sensor i : fullList) { 430 if (i.getType() == type) { 431 list.add(i); 432 } 433 } 434 } 435 list = Collections.unmodifiableList(list); 436 mSensorListByType.append(type, list); 437 } 438 } 439 return list; 440 } 441 442 /** 443 * Use this method to get a list of available dynamic sensors of a certain type. 444 * Make multiple calls to get sensors of different types or use 445 * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all dynamic sensors. 446 * 447 * <p class="note"> 448 * NOTE: Both wake-up and non wake-up sensors matching the given type are 449 * returned. Check {@link Sensor#isWakeUpSensor()} to know the wake-up properties 450 * of the returned {@link Sensor}. 451 * </p> 452 * 453 * @param type of sensors requested 454 * 455 * @return a list of dynamic sensors matching the requested type. 456 * 457 * @see Sensor 458 */ getDynamicSensorList(int type)459 public List<Sensor> getDynamicSensorList(int type) { 460 // cache the returned lists the first time 461 final List<Sensor> fullList = getFullDynamicSensorList(); 462 if (type == Sensor.TYPE_ALL) { 463 return Collections.unmodifiableList(fullList); 464 } else { 465 List<Sensor> list = new ArrayList(); 466 for (Sensor i : fullList) { 467 if (i.getType() == type) { 468 list.add(i); 469 } 470 } 471 return Collections.unmodifiableList(list); 472 } 473 } 474 475 /** 476 * Use this method to get the default sensor for a given type. Note that the 477 * returned sensor could be a composite sensor, and its data could be 478 * averaged or filtered. If you need to access the raw sensors use 479 * {@link SensorManager#getSensorList(int) getSensorList}. 480 * 481 * @param type 482 * of sensors requested 483 * 484 * @return the default sensor matching the requested type if one exists and the application 485 * has the necessary permissions, or null otherwise. 486 * 487 * @see #getSensorList(int) 488 * @see Sensor 489 */ getDefaultSensor(int type)490 public Sensor getDefaultSensor(int type) { 491 // TODO: need to be smarter, for now, just return the 1st sensor 492 List<Sensor> l = getSensorList(type); 493 boolean wakeUpSensor = false; 494 // For the following sensor types, return a wake-up sensor. These types are by default 495 // defined as wake-up sensors. For the rest of the SDK defined sensor types return a 496 // non_wake-up version. 497 if (type == Sensor.TYPE_PROXIMITY || type == Sensor.TYPE_SIGNIFICANT_MOTION 498 || type == Sensor.TYPE_TILT_DETECTOR || type == Sensor.TYPE_WAKE_GESTURE 499 || type == Sensor.TYPE_GLANCE_GESTURE || type == Sensor.TYPE_PICK_UP_GESTURE 500 || type == Sensor.TYPE_WRIST_TILT_GESTURE 501 || type == Sensor.TYPE_DYNAMIC_SENSOR_META) { 502 wakeUpSensor = true; 503 } 504 505 for (Sensor sensor : l) { 506 if (sensor.isWakeUpSensor() == wakeUpSensor) return sensor; 507 } 508 return null; 509 } 510 511 /** 512 * Return a Sensor with the given type and wakeUp properties. If multiple sensors of this 513 * type exist, any one of them may be returned. 514 * <p> 515 * For example, 516 * <ul> 517 * <li>getDefaultSensor({@link Sensor#TYPE_ACCELEROMETER}, true) returns a wake-up 518 * accelerometer sensor if it exists. </li> 519 * <li>getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, false) returns a non wake-up 520 * proximity sensor if it exists. </li> 521 * <li>getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, true) returns a wake-up proximity 522 * sensor which is the same as the Sensor returned by {@link #getDefaultSensor(int)}. </li> 523 * </ul> 524 * </p> 525 * <p class="note"> 526 * Note: Sensors like {@link Sensor#TYPE_PROXIMITY} and {@link Sensor#TYPE_SIGNIFICANT_MOTION} 527 * are declared as wake-up sensors by default. 528 * </p> 529 * @param type 530 * type of sensor requested 531 * @param wakeUp 532 * flag to indicate whether the Sensor is a wake-up or non wake-up sensor. 533 * @return the default sensor matching the requested type and wakeUp properties if one exists 534 * and the application has the necessary permissions, or null otherwise. 535 * @see Sensor#isWakeUpSensor() 536 */ getDefaultSensor(int type, boolean wakeUp)537 public Sensor getDefaultSensor(int type, boolean wakeUp) { 538 List<Sensor> l = getSensorList(type); 539 for (Sensor sensor : l) { 540 if (sensor.isWakeUpSensor() == wakeUp) { 541 return sensor; 542 } 543 } 544 return null; 545 } 546 547 /** 548 * Registers a listener for given sensors. 549 * 550 * @deprecated This method is deprecated, use 551 * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)} 552 * instead. 553 * 554 * @param listener 555 * sensor listener object 556 * 557 * @param sensors 558 * a bit masks of the sensors to register to 559 * 560 * @return <code>true</code> if the sensor is supported and successfully 561 * enabled 562 */ 563 @Deprecated registerListener(SensorListener listener, int sensors)564 public boolean registerListener(SensorListener listener, int sensors) { 565 return registerListener(listener, sensors, SENSOR_DELAY_NORMAL); 566 } 567 568 /** 569 * Registers a SensorListener for given sensors. 570 * 571 * @deprecated This method is deprecated, use 572 * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)} 573 * instead. 574 * 575 * @param listener 576 * sensor listener object 577 * 578 * @param sensors 579 * a bit masks of the sensors to register to 580 * 581 * @param rate 582 * rate of events. This is only a hint to the system. events may be 583 * received faster or slower than the specified rate. Usually events 584 * are received faster. The value must be one of 585 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 586 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}. 587 * 588 * @return <code>true</code> if the sensor is supported and successfully 589 * enabled 590 */ 591 @Deprecated registerListener(SensorListener listener, int sensors, int rate)592 public boolean registerListener(SensorListener listener, int sensors, int rate) { 593 return getLegacySensorManager().registerListener(listener, sensors, rate); 594 } 595 596 /** 597 * Unregisters a listener for all sensors. 598 * 599 * @deprecated This method is deprecated, use 600 * {@link SensorManager#unregisterListener(SensorEventListener)} 601 * instead. 602 * 603 * @param listener 604 * a SensorListener object 605 */ 606 @Deprecated unregisterListener(SensorListener listener)607 public void unregisterListener(SensorListener listener) { 608 unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW); 609 } 610 611 /** 612 * Unregisters a listener for the sensors with which it is registered. 613 * 614 * @deprecated This method is deprecated, use 615 * {@link SensorManager#unregisterListener(SensorEventListener, Sensor)} 616 * instead. 617 * 618 * @param listener 619 * a SensorListener object 620 * 621 * @param sensors 622 * a bit masks of the sensors to unregister from 623 */ 624 @Deprecated unregisterListener(SensorListener listener, int sensors)625 public void unregisterListener(SensorListener listener, int sensors) { 626 getLegacySensorManager().unregisterListener(listener, sensors); 627 } 628 629 /** 630 * Unregisters a listener for the sensors with which it is registered. 631 * 632 * <p class="note"></p> 633 * Note: Don't use this method with a one shot trigger sensor such as 634 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. 635 * Use {@link #cancelTriggerSensor(TriggerEventListener, Sensor)} instead. 636 * </p> 637 * 638 * @param listener 639 * a SensorEventListener object 640 * 641 * @param sensor 642 * the sensor to unregister from 643 * 644 * @see #unregisterListener(SensorEventListener) 645 * @see #registerListener(SensorEventListener, Sensor, int) 646 */ unregisterListener(SensorEventListener listener, Sensor sensor)647 public void unregisterListener(SensorEventListener listener, Sensor sensor) { 648 if (listener == null || sensor == null) { 649 return; 650 } 651 652 unregisterListenerImpl(listener, sensor); 653 } 654 655 /** 656 * Unregisters a listener for all sensors. 657 * 658 * @param listener 659 * a SensorListener object 660 * 661 * @see #unregisterListener(SensorEventListener, Sensor) 662 * @see #registerListener(SensorEventListener, Sensor, int) 663 * 664 */ unregisterListener(SensorEventListener listener)665 public void unregisterListener(SensorEventListener listener) { 666 if (listener == null) { 667 return; 668 } 669 670 unregisterListenerImpl(listener, null); 671 } 672 673 /** @hide */ unregisterListenerImpl(SensorEventListener listener, Sensor sensor)674 protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor sensor); 675 676 /** 677 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given 678 * sensor at the given sampling frequency. 679 * <p> 680 * The events will be delivered to the provided {@code SensorEventListener} as soon as they are 681 * available. To reduce the power consumption, applications can use 682 * {@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a 683 * positive non-zero maximum reporting latency. 684 * </p> 685 * <p> 686 * In the case of non-wake-up sensors, the events are only delivered while the Application 687 * Processor (AP) is not in suspend mode. See {@link Sensor#isWakeUpSensor()} for more details. 688 * To ensure delivery of events from non-wake-up sensors even when the screen is OFF, the 689 * application registering to the sensor must hold a partial wake-lock to keep the AP awake, 690 * otherwise some events might be lost while the AP is asleep. Note that although events might 691 * be lost while the AP is asleep, the sensor will still consume power if it is not explicitly 692 * deactivated by the application. Applications must unregister their {@code 693 * SensorEventListener}s in their activity's {@code onPause()} method to avoid consuming power 694 * while the device is inactive. See {@link #registerListener(SensorEventListener, Sensor, int, 695 * int)} for more details on hardware FIFO (queueing) capabilities and when some sensor events 696 * might be lost. 697 * </p> 698 * <p> 699 * In the case of wake-up sensors, each event generated by the sensor will cause the AP to 700 * wake-up, ensuring that each event can be delivered. Because of this, registering to a wake-up 701 * sensor has very significant power implications. Call {@link Sensor#isWakeUpSensor()} to check 702 * whether a sensor is a wake-up sensor. See 703 * {@link #registerListener(SensorEventListener, Sensor, int, int)} for information on how to 704 * reduce the power impact of registering to wake-up sensors. 705 * </p> 706 * <p class="note"> 707 * Note: Don't use this method with one-shot trigger sensors such as 708 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use 709 * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. Use 710 * {@link Sensor#getReportingMode()} to obtain the reporting mode of a given sensor. 711 * </p> 712 * 713 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object. 714 * @param sensor The {@link android.hardware.Sensor Sensor} to register to. 715 * @param samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are 716 * delivered at. This is only a hint to the system. Events may be received faster or 717 * slower than the specified rate. Usually events are received faster. The value must 718 * be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 719 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired delay 720 * between events in microseconds. Specifying the delay in microseconds only works 721 * from Android 2.3 (API level 9) onwards. For earlier releases, you must use one of 722 * the {@code SENSOR_DELAY_*} constants. 723 * @return <code>true</code> if the sensor is supported and successfully enabled. 724 * @see #registerListener(SensorEventListener, Sensor, int, Handler) 725 * @see #unregisterListener(SensorEventListener) 726 * @see #unregisterListener(SensorEventListener, Sensor) 727 */ registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs)728 public boolean registerListener(SensorEventListener listener, Sensor sensor, 729 int samplingPeriodUs) { 730 return registerListener(listener, sensor, samplingPeriodUs, null); 731 } 732 733 /** 734 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given 735 * sensor at the given sampling frequency and the given maximum reporting latency. 736 * <p> 737 * This function is similar to {@link #registerListener(SensorEventListener, Sensor, int)} but 738 * it allows events to stay temporarily in the hardware FIFO (queue) before being delivered. The 739 * events can be stored in the hardware FIFO up to {@code maxReportLatencyUs} microseconds. Once 740 * one of the events in the FIFO needs to be reported, all of the events in the FIFO are 741 * reported sequentially. This means that some events will be reported before the maximum 742 * reporting latency has elapsed. 743 * </p><p> 744 * When {@code maxReportLatencyUs} is 0, the call is equivalent to a call to 745 * {@link #registerListener(SensorEventListener, Sensor, int)}, as it requires the events to be 746 * delivered as soon as possible. 747 * </p><p> 748 * When {@code sensor.maxFifoEventCount()} is 0, the sensor does not use a FIFO, so the call 749 * will also be equivalent to {@link #registerListener(SensorEventListener, Sensor, int)}. 750 * </p><p> 751 * Setting {@code maxReportLatencyUs} to a positive value allows to reduce the number of 752 * interrupts the AP (Application Processor) receives, hence reducing power consumption, as the 753 * AP can switch to a lower power state while the sensor is capturing the data. This is 754 * especially important when registering to wake-up sensors, for which each interrupt causes the 755 * AP to wake up if it was in suspend mode. See {@link Sensor#isWakeUpSensor()} for more 756 * information on wake-up sensors. 757 * </p> 758 * <p class="note"> 759 * </p> 760 * Note: Don't use this method with one-shot trigger sensors such as 761 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use 762 * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p> 763 * 764 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object 765 * that will receive the sensor events. If the application is interested in receiving 766 * flush complete notifications, it should register with 767 * {@link android.hardware.SensorEventListener SensorEventListener2} instead. 768 * @param sensor The {@link android.hardware.Sensor Sensor} to register to. 769 * @param samplingPeriodUs The desired delay between two consecutive events in microseconds. 770 * This is only a hint to the system. Events may be received faster or slower than 771 * the specified rate. Usually events are received faster. Can be one of 772 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 773 * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in 774 * microseconds. 775 * @param maxReportLatencyUs Maximum time in microseconds that events can be delayed before 776 * being reported to the application. A large value allows reducing the power 777 * consumption associated with the sensor. If maxReportLatencyUs is set to zero, 778 * events are delivered as soon as they are available, which is equivalent to calling 779 * {@link #registerListener(SensorEventListener, Sensor, int)}. 780 * @return <code>true</code> if the sensor is supported and successfully enabled. 781 * @see #registerListener(SensorEventListener, Sensor, int) 782 * @see #unregisterListener(SensorEventListener) 783 * @see #flush(SensorEventListener) 784 */ registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, int maxReportLatencyUs)785 public boolean registerListener(SensorEventListener listener, Sensor sensor, 786 int samplingPeriodUs, int maxReportLatencyUs) { 787 int delay = getDelay(samplingPeriodUs); 788 return registerListenerImpl(listener, sensor, delay, null, maxReportLatencyUs, 0); 789 } 790 791 /** 792 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given 793 * sensor. Events are delivered in continuous mode as soon as they are available. To reduce the 794 * power consumption, applications can use 795 * {@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a 796 * positive non-zero maximum reporting latency. 797 * <p class="note"> 798 * </p> 799 * Note: Don't use this method with a one shot trigger sensor such as 800 * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use 801 * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p> 802 * 803 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object. 804 * @param sensor The {@link android.hardware.Sensor Sensor} to register to. 805 * @param samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are 806 * delivered at. This is only a hint to the system. Events may be received faster or 807 * slower than the specified rate. Usually events are received faster. The value must 808 * be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 809 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired 810 * delay between events in microseconds. Specifying the delay in microseconds only 811 * works from Android 2.3 (API level 9) onwards. For earlier releases, you must use 812 * one of the {@code SENSOR_DELAY_*} constants. 813 * @param handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent 814 * sensor events} will be delivered to. 815 * @return <code>true</code> if the sensor is supported and successfully enabled. 816 * @see #registerListener(SensorEventListener, Sensor, int) 817 * @see #unregisterListener(SensorEventListener) 818 * @see #unregisterListener(SensorEventListener, Sensor) 819 */ registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, Handler handler)820 public boolean registerListener(SensorEventListener listener, Sensor sensor, 821 int samplingPeriodUs, Handler handler) { 822 int delay = getDelay(samplingPeriodUs); 823 return registerListenerImpl(listener, sensor, delay, handler, 0, 0); 824 } 825 826 /** 827 * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given 828 * sensor at the given sampling frequency and the given maximum reporting latency. 829 * 830 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object 831 * that will receive the sensor events. If the application is interested in receiving 832 * flush complete notifications, it should register with 833 * {@link android.hardware.SensorEventListener SensorEventListener2} instead. 834 * @param sensor The {@link android.hardware.Sensor Sensor} to register to. 835 * @param samplingPeriodUs The desired delay between two consecutive events in microseconds. 836 * This is only a hint to the system. Events may be received faster or slower than 837 * the specified rate. Usually events are received faster. Can be one of 838 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 839 * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in 840 * microseconds. 841 * @param maxReportLatencyUs Maximum time in microseconds that events can be delayed before 842 * being reported to the application. A large value allows reducing the power 843 * consumption associated with the sensor. If maxReportLatencyUs is set to zero, 844 * events are delivered as soon as they are available, which is equivalent to calling 845 * {@link #registerListener(SensorEventListener, Sensor, int)}. 846 * @param handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent 847 * sensor events} will be delivered to. 848 * @return <code>true</code> if the sensor is supported and successfully enabled. 849 * @see #registerListener(SensorEventListener, Sensor, int, int) 850 */ registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, int maxReportLatencyUs, Handler handler)851 public boolean registerListener(SensorEventListener listener, Sensor sensor, 852 int samplingPeriodUs, int maxReportLatencyUs, Handler handler) { 853 int delayUs = getDelay(samplingPeriodUs); 854 return registerListenerImpl(listener, sensor, delayUs, handler, maxReportLatencyUs, 0); 855 } 856 857 /** @hide */ registerListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags)858 protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, 859 int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags); 860 861 862 /** 863 * Flushes the FIFO of all the sensors registered for this listener. If there are events 864 * in the FIFO of the sensor, they are returned as if the maxReportLantecy of the FIFO has 865 * expired. Events are returned in the usual way through the SensorEventListener. 866 * This call doesn't affect the maxReportLantecy for this sensor. This call is asynchronous and 867 * returns immediately. 868 * {@link android.hardware.SensorEventListener2#onFlushCompleted onFlushCompleted} is called 869 * after all the events in the batch at the time of calling this method have been delivered 870 * successfully. If the hardware doesn't support flush, it still returns true and a trivial 871 * flush complete event is sent after the current event for all the clients registered for this 872 * sensor. 873 * 874 * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object 875 * which was previously used in a registerListener call. 876 * @return <code>true</code> if the flush is initiated successfully on all the sensors 877 * registered for this listener, false if no sensor is previously registered for this 878 * listener or flush on one of the sensors fails. 879 * @see #registerListener(SensorEventListener, Sensor, int, int) 880 * @throws IllegalArgumentException when listener is null. 881 */ flush(SensorEventListener listener)882 public boolean flush(SensorEventListener listener) { 883 return flushImpl(listener); 884 } 885 886 /** @hide */ flushImpl(SensorEventListener listener)887 protected abstract boolean flushImpl(SensorEventListener listener); 888 889 890 /** 891 * Create a sensor direct channel backed by shared memory wrapped in MemoryFile object. 892 * 893 * The resulting channel can be used for delivering sensor events to native code, other 894 * processes, GPU/DSP or other co-processors without CPU intervention. This is the recommanded 895 * for high performance sensor applications that use high sensor rates (e.g. greater than 200Hz) 896 * and cares about sensor event latency. 897 * 898 * Use the returned {@link android.hardware.SensorDirectChannel} object to configure direct 899 * report of sensor events. After use, call {@link android.hardware.SensorDirectChannel#close()} 900 * to free up resource in sensor system associated with the direct channel. 901 * 902 * @param mem A {@link android.os.MemoryFile} shared memory object. 903 * @return A {@link android.hardware.SensorDirectChannel} object. 904 * @throws NullPointerException when mem is null. 905 * @throws UncheckedIOException if not able to create channel. 906 * @see SensorDirectChannel#close() 907 */ createDirectChannel(MemoryFile mem)908 public SensorDirectChannel createDirectChannel(MemoryFile mem) { 909 return createDirectChannelImpl(mem, null); 910 } 911 912 /** 913 * Create a sensor direct channel backed by shared memory wrapped in HardwareBuffer object. 914 * 915 * The resulting channel can be used for delivering sensor events to native code, other 916 * processes, GPU/DSP or other co-processors without CPU intervention. This is the recommanded 917 * for high performance sensor applications that use high sensor rates (e.g. greater than 200Hz) 918 * and cares about sensor event latency. 919 * 920 * Use the returned {@link android.hardware.SensorDirectChannel} object to configure direct 921 * report of sensor events. After use, call {@link android.hardware.SensorDirectChannel#close()} 922 * to free up resource in sensor system associated with the direct channel. 923 * 924 * @param mem A {@link android.hardware.HardwareBuffer} shared memory object. 925 * @return A {@link android.hardware.SensorDirectChannel} object. 926 * @throws NullPointerException when mem is null. 927 * @throws UncheckedIOException if not able to create channel. 928 * @see SensorDirectChannel#close() 929 */ createDirectChannel(HardwareBuffer mem)930 public SensorDirectChannel createDirectChannel(HardwareBuffer mem) { 931 return createDirectChannelImpl(null, mem); 932 } 933 934 /** @hide */ createDirectChannelImpl( MemoryFile memoryFile, HardwareBuffer hardwareBuffer)935 protected abstract SensorDirectChannel createDirectChannelImpl( 936 MemoryFile memoryFile, HardwareBuffer hardwareBuffer); 937 938 /** @hide */ destroyDirectChannel(SensorDirectChannel channel)939 void destroyDirectChannel(SensorDirectChannel channel) { 940 destroyDirectChannelImpl(channel); 941 } 942 943 /** @hide */ destroyDirectChannelImpl(SensorDirectChannel channel)944 protected abstract void destroyDirectChannelImpl(SensorDirectChannel channel); 945 946 /** @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 #registerDynamicSensorCallback(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