SensorManager.java revision 04d7e83e65e246e154b5b346e3eb0081b741ae88
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.os.Looper; 20import android.os.Process; 21import android.os.RemoteException; 22import android.os.Handler; 23import android.os.Message; 24import android.os.ServiceManager; 25import android.util.Log; 26import android.util.SparseArray; 27import android.view.IRotationWatcher; 28import android.view.IWindowManager; 29import android.view.Surface; 30 31import java.util.ArrayList; 32import java.util.Collections; 33import java.util.HashMap; 34import java.util.List; 35 36/** 37 * SensorManager lets you access the device's {@link android.hardware.Sensor 38 * sensors}. Get an instance of this class by calling 39 * {@link android.content.Context#getSystemService(java.lang.String) 40 * Context.getSystemService()} with the argument 41 * {@link android.content.Context#SENSOR_SERVICE}. 42 * 43 * <pre class="prettyprint"> 44 * public class SensorActivity extends Activity, implements SensorEventListener { 45 * private final SensorManager mSensorManager; 46 * private final Sensor mAccelerometer; 47 * 48 * public SensorActivity() { 49 * mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE); 50 * mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 51 * mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); 52 * } 53 * 54 * public void onAccuracyChanged(Sensor sensor, int accuracy) { 55 * } 56 * 57 * public abstract void onSensorChanged(SensorEvent event) { 58 * } 59 * } 60 * </pre> 61 * 62 * @see SensorEventListener 63 * @see SensorEvent 64 * @see Sensor 65 * 66 */ 67public class SensorManager 68{ 69 private static final String TAG = "SensorManager"; 70 private static final float[] mTempMatrix = new float[16]; 71 72 /* NOTE: sensor IDs must be a power of 2 */ 73 74 /** 75 * A constant describing an orientation sensor. See 76 * {@link android.hardware.SensorListener SensorListener} for more details. 77 * 78 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 79 */ 80 @Deprecated 81 public static final int SENSOR_ORIENTATION = 1 << 0; 82 83 /** 84 * A constant describing an accelerometer. See 85 * {@link android.hardware.SensorListener SensorListener} for more details. 86 * 87 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 88 */ 89 @Deprecated 90 public static final int SENSOR_ACCELEROMETER = 1 << 1; 91 92 /** 93 * A constant describing a temperature sensor See 94 * {@link android.hardware.SensorListener SensorListener} for more details. 95 * 96 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 97 */ 98 @Deprecated 99 public static final int SENSOR_TEMPERATURE = 1 << 2; 100 101 /** 102 * A constant describing a magnetic sensor See 103 * {@link android.hardware.SensorListener SensorListener} for more details. 104 * 105 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 106 */ 107 @Deprecated 108 public static final int SENSOR_MAGNETIC_FIELD = 1 << 3; 109 110 /** 111 * A constant describing an ambient light sensor See 112 * {@link android.hardware.SensorListener SensorListener} for more details. 113 * 114 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 115 */ 116 @Deprecated 117 public static final int SENSOR_LIGHT = 1 << 4; 118 119 /** 120 * A constant describing a proximity sensor See 121 * {@link android.hardware.SensorListener SensorListener} for more details. 122 * 123 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 124 */ 125 @Deprecated 126 public static final int SENSOR_PROXIMITY = 1 << 5; 127 128 /** 129 * A constant describing a Tricorder See 130 * {@link android.hardware.SensorListener SensorListener} for more details. 131 * 132 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 133 */ 134 @Deprecated 135 public static final int SENSOR_TRICORDER = 1 << 6; 136 137 /** 138 * A constant describing an orientation sensor. See 139 * {@link android.hardware.SensorListener SensorListener} for more details. 140 * 141 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 142 */ 143 @Deprecated 144 public static final int SENSOR_ORIENTATION_RAW = 1 << 7; 145 146 /** 147 * A constant that includes all sensors 148 * 149 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 150 */ 151 @Deprecated 152 public static final int SENSOR_ALL = 0x7F; 153 154 /** 155 * Smallest sensor ID 156 * 157 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 158 */ 159 @Deprecated 160 public static final int SENSOR_MIN = SENSOR_ORIENTATION; 161 162 /** 163 * Largest sensor ID 164 * 165 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 166 */ 167 @Deprecated 168 public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1); 169 170 171 /** 172 * Index of the X value in the array returned by 173 * {@link android.hardware.SensorListener#onSensorChanged} 174 * 175 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 176 */ 177 @Deprecated 178 public static final int DATA_X = 0; 179 180 /** 181 * Index of the Y value in the array returned by 182 * {@link android.hardware.SensorListener#onSensorChanged} 183 * 184 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 185 */ 186 @Deprecated 187 public static final int DATA_Y = 1; 188 189 /** 190 * Index of the Z value in the array returned by 191 * {@link android.hardware.SensorListener#onSensorChanged} 192 * 193 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 194 */ 195 @Deprecated 196 public static final int DATA_Z = 2; 197 198 /** 199 * Offset to the untransformed values in the array returned by 200 * {@link android.hardware.SensorListener#onSensorChanged} 201 * 202 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 203 */ 204 @Deprecated 205 public static final int RAW_DATA_INDEX = 3; 206 207 /** 208 * Index of the untransformed X value in the array returned by 209 * {@link android.hardware.SensorListener#onSensorChanged} 210 * 211 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 212 */ 213 @Deprecated 214 public static final int RAW_DATA_X = 3; 215 216 /** 217 * Index of the untransformed Y value in the array returned by 218 * {@link android.hardware.SensorListener#onSensorChanged} 219 * 220 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 221 */ 222 @Deprecated 223 public static final int RAW_DATA_Y = 4; 224 225 /** 226 * Index of the untransformed Z value in the array returned by 227 * {@link android.hardware.SensorListener#onSensorChanged} 228 * 229 * @deprecated use {@link android.hardware.Sensor Sensor} instead. 230 */ 231 @Deprecated 232 public static final int RAW_DATA_Z = 5; 233 234 /** Standard gravity (g) on Earth. This value is equivalent to 1G */ 235 public static final float STANDARD_GRAVITY = 9.80665f; 236 237 /** Sun's gravity in SI units (m/s^2) */ 238 public static final float GRAVITY_SUN = 275.0f; 239 /** Mercury's gravity in SI units (m/s^2) */ 240 public static final float GRAVITY_MERCURY = 3.70f; 241 /** Venus' gravity in SI units (m/s^2) */ 242 public static final float GRAVITY_VENUS = 8.87f; 243 /** Earth's gravity in SI units (m/s^2) */ 244 public static final float GRAVITY_EARTH = 9.80665f; 245 /** The Moon's gravity in SI units (m/s^2) */ 246 public static final float GRAVITY_MOON = 1.6f; 247 /** Mars' gravity in SI units (m/s^2) */ 248 public static final float GRAVITY_MARS = 3.71f; 249 /** Jupiter's gravity in SI units (m/s^2) */ 250 public static final float GRAVITY_JUPITER = 23.12f; 251 /** Saturn's gravity in SI units (m/s^2) */ 252 public static final float GRAVITY_SATURN = 8.96f; 253 /** Uranus' gravity in SI units (m/s^2) */ 254 public static final float GRAVITY_URANUS = 8.69f; 255 /** Neptune's gravity in SI units (m/s^2) */ 256 public static final float GRAVITY_NEPTUNE = 11.0f; 257 /** Pluto's gravity in SI units (m/s^2) */ 258 public static final float GRAVITY_PLUTO = 0.6f; 259 /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */ 260 public static final float GRAVITY_DEATH_STAR_I = 0.000000353036145f; 261 /** Gravity on the island */ 262 public static final float GRAVITY_THE_ISLAND = 4.815162342f; 263 264 265 /** Maximum magnetic field on Earth's surface */ 266 public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f; 267 /** Minimum magnetic field on Earth's surface */ 268 public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f; 269 270 271 /** Standard atmosphere, or average sea-level pressure in hPa (millibar) */ 272 public static final float PRESSURE_STANDARD_ATMOSPHERE = 1013.25f; 273 274 275 /** Maximum luminance of sunlight in lux */ 276 public static final float LIGHT_SUNLIGHT_MAX = 120000.0f; 277 /** luminance of sunlight in lux */ 278 public static final float LIGHT_SUNLIGHT = 110000.0f; 279 /** luminance in shade in lux */ 280 public static final float LIGHT_SHADE = 20000.0f; 281 /** luminance under an overcast sky in lux */ 282 public static final float LIGHT_OVERCAST = 10000.0f; 283 /** luminance at sunrise in lux */ 284 public static final float LIGHT_SUNRISE = 400.0f; 285 /** luminance under a cloudy sky in lux */ 286 public static final float LIGHT_CLOUDY = 100.0f; 287 /** luminance at night with full moon in lux */ 288 public static final float LIGHT_FULLMOON = 0.25f; 289 /** luminance at night with no moon in lux*/ 290 public static final float LIGHT_NO_MOON = 0.001f; 291 292 293 /** get sensor data as fast as possible */ 294 public static final int SENSOR_DELAY_FASTEST = 0; 295 /** rate suitable for games */ 296 public static final int SENSOR_DELAY_GAME = 1; 297 /** rate suitable for the user interface */ 298 public static final int SENSOR_DELAY_UI = 2; 299 /** rate (default) suitable for screen orientation changes */ 300 public static final int SENSOR_DELAY_NORMAL = 3; 301 302 303 /** 304 * The values returned by this sensor cannot be trusted, calibration is 305 * needed or the environment doesn't allow readings 306 */ 307 public static final int SENSOR_STATUS_UNRELIABLE = 0; 308 309 /** 310 * This sensor is reporting data with low accuracy, calibration with the 311 * environment is needed 312 */ 313 public static final int SENSOR_STATUS_ACCURACY_LOW = 1; 314 315 /** 316 * This sensor is reporting data with an average level of accuracy, 317 * calibration with the environment may improve the readings 318 */ 319 public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2; 320 321 /** This sensor is reporting data with maximum accuracy */ 322 public static final int SENSOR_STATUS_ACCURACY_HIGH = 3; 323 324 /** see {@link #remapCoordinateSystem} */ 325 public static final int AXIS_X = 1; 326 /** see {@link #remapCoordinateSystem} */ 327 public static final int AXIS_Y = 2; 328 /** see {@link #remapCoordinateSystem} */ 329 public static final int AXIS_Z = 3; 330 /** see {@link #remapCoordinateSystem} */ 331 public static final int AXIS_MINUS_X = AXIS_X | 0x80; 332 /** see {@link #remapCoordinateSystem} */ 333 public static final int AXIS_MINUS_Y = AXIS_Y | 0x80; 334 /** see {@link #remapCoordinateSystem} */ 335 public static final int AXIS_MINUS_Z = AXIS_Z | 0x80; 336 337 /*-----------------------------------------------------------------------*/ 338 339 Looper mMainLooper; 340 @SuppressWarnings("deprecation") 341 private HashMap<SensorListener, LegacyListener> mLegacyListenersMap = 342 new HashMap<SensorListener, LegacyListener>(); 343 344 /*-----------------------------------------------------------------------*/ 345 346 private static final int SENSOR_DISABLE = -1; 347 private static boolean sSensorModuleInitialized = false; 348 private static ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>(); 349 private static SparseArray<List<Sensor>> sSensorListByType = new SparseArray<List<Sensor>>(); 350 private static IWindowManager sWindowManager; 351 private static int sRotation = Surface.ROTATION_0; 352 /* The thread and the sensor list are global to the process 353 * but the actual thread is spawned on demand */ 354 private static SensorThread sSensorThread; 355 private static int sQueue; 356 357 // Used within this module from outside SensorManager, don't make private 358 static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>(); 359 static final ArrayList<ListenerDelegate> sListeners = 360 new ArrayList<ListenerDelegate>(); 361 362 /*-----------------------------------------------------------------------*/ 363 364 static private class SensorThread { 365 366 Thread mThread; 367 boolean mSensorsReady; 368 369 SensorThread() { 370 } 371 372 @Override 373 protected void finalize() { 374 } 375 376 // must be called with sListeners lock 377 boolean startLocked() { 378 try { 379 if (mThread == null) { 380 mSensorsReady = false; 381 SensorThreadRunnable runnable = new SensorThreadRunnable(); 382 Thread thread = new Thread(runnable, SensorThread.class.getName()); 383 thread.start(); 384 synchronized (runnable) { 385 while (mSensorsReady == false) { 386 runnable.wait(); 387 } 388 } 389 mThread = thread; 390 } 391 } catch (InterruptedException e) { 392 } 393 return mThread == null ? false : true; 394 } 395 396 private class SensorThreadRunnable implements Runnable { 397 SensorThreadRunnable() { 398 } 399 400 private boolean open() { 401 // NOTE: this cannot synchronize on sListeners, since 402 // it's held in the main thread at least until we 403 // return from here. 404 sQueue = sensors_create_queue(); 405 return true; 406 } 407 408 public void run() { 409 //Log.d(TAG, "entering main sensor thread"); 410 final float[] values = new float[3]; 411 final int[] status = new int[1]; 412 final long timestamp[] = new long[1]; 413 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 414 415 if (!open()) { 416 return; 417 } 418 419 synchronized (this) { 420 // we've open the driver, we're ready to open the sensors 421 mSensorsReady = true; 422 this.notify(); 423 } 424 425 while (true) { 426 // wait for an event 427 final int sensor = sensors_data_poll(sQueue, values, status, timestamp); 428 429 int accuracy = status[0]; 430 synchronized (sListeners) { 431 if (sensor == -1 || sListeners.isEmpty()) { 432 if (sensor == -1) { 433 // we lost the connection to the event stream. this happens 434 // when the last listener is removed. 435 Log.d(TAG, "_sensors_data_poll() failed, we bail out."); 436 } 437 438 // we have no more listeners or polling failed, terminate the thread 439 sensors_destroy_queue(sQueue); 440 sQueue = 0; 441 mThread = null; 442 break; 443 } 444 final Sensor sensorObject = sHandleToSensor.get(sensor); 445 if (sensorObject != null) { 446 // report the sensor event to all listeners that 447 // care about it. 448 final int size = sListeners.size(); 449 for (int i=0 ; i<size ; i++) { 450 ListenerDelegate listener = sListeners.get(i); 451 if (listener.hasSensor(sensorObject)) { 452 // this is asynchronous (okay to call 453 // with sListeners lock held). 454 listener.onSensorChangedLocked(sensorObject, 455 values, timestamp, accuracy); 456 } 457 } 458 } 459 } 460 } 461 //Log.d(TAG, "exiting main sensor thread"); 462 } 463 } 464 } 465 466 /*-----------------------------------------------------------------------*/ 467 468 private class ListenerDelegate { 469 final SensorEventListener mSensorEventListener; 470 private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>(); 471 private final Handler mHandler; 472 private SensorEvent mValuesPool; 473 public int mSensors; 474 475 ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) { 476 mSensorEventListener = listener; 477 Looper looper = (handler != null) ? handler.getLooper() : mMainLooper; 478 // currently we create one Handler instance per listener, but we could 479 // have one per looper (we'd need to pass the ListenerDelegate 480 // instance to handleMessage and keep track of them separately). 481 mHandler = new Handler(looper) { 482 @Override 483 public void handleMessage(Message msg) { 484 SensorEvent t = (SensorEvent)msg.obj; 485 if (t.accuracy >= 0) { 486 mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy); 487 } 488 mSensorEventListener.onSensorChanged(t); 489 returnToPool(t); 490 } 491 }; 492 addSensor(sensor); 493 } 494 495 protected SensorEvent createSensorEvent() { 496 // maximal size for all legacy events is 3 497 return new SensorEvent(3); 498 } 499 500 protected SensorEvent getFromPool() { 501 SensorEvent t = null; 502 synchronized (this) { 503 // remove the array from the pool 504 t = mValuesPool; 505 mValuesPool = null; 506 } 507 if (t == null) { 508 // the pool was empty, we need a new one 509 t = createSensorEvent(); 510 } 511 return t; 512 } 513 514 protected void returnToPool(SensorEvent t) { 515 synchronized (this) { 516 // put back the array into the pool 517 if (mValuesPool == null) { 518 mValuesPool = t; 519 } 520 } 521 } 522 523 Object getListener() { 524 return mSensorEventListener; 525 } 526 527 int addSensor(Sensor sensor) { 528 mSensors |= 1<<sensor.getHandle(); 529 mSensorList.add(sensor); 530 return mSensors; 531 } 532 int removeSensor(Sensor sensor) { 533 mSensors &= ~(1<<sensor.getHandle()); 534 mSensorList.remove(sensor); 535 return mSensors; 536 } 537 boolean hasSensor(Sensor sensor) { 538 return ((mSensors & (1<<sensor.getHandle())) != 0); 539 } 540 List<Sensor> getSensors() { 541 return mSensorList; 542 } 543 544 void onSensorChangedLocked(Sensor sensor, float[] values, long[] timestamp, int accuracy) { 545 SensorEvent t = getFromPool(); 546 final float[] v = t.values; 547 v[0] = values[0]; 548 v[1] = values[1]; 549 v[2] = values[2]; 550 t.timestamp = timestamp[0]; 551 t.accuracy = accuracy; 552 t.sensor = sensor; 553 Message msg = Message.obtain(); 554 msg.what = 0; 555 msg.obj = t; 556 mHandler.sendMessage(msg); 557 } 558 } 559 560 /** 561 * {@hide} 562 */ 563 public SensorManager(Looper mainLooper) { 564 mMainLooper = mainLooper; 565 566 567 synchronized(sListeners) { 568 if (!sSensorModuleInitialized) { 569 sSensorModuleInitialized = true; 570 571 nativeClassInit(); 572 573 sWindowManager = IWindowManager.Stub.asInterface( 574 ServiceManager.getService("window")); 575 if (sWindowManager != null) { 576 // if it's null we're running in the system process 577 // which won't get the rotated values 578 try { 579 sRotation = sWindowManager.watchRotation( 580 new IRotationWatcher.Stub() { 581 public void onRotationChanged(int rotation) { 582 SensorManager.this.onRotationChanged(rotation); 583 } 584 } 585 ); 586 } catch (RemoteException e) { 587 } 588 } 589 590 // initialize the sensor list 591 sensors_module_init(); 592 final ArrayList<Sensor> fullList = sFullSensorsList; 593 int i = 0; 594 do { 595 Sensor sensor = new Sensor(); 596 i = sensors_module_get_next_sensor(sensor, i); 597 598 if (i>=0) { 599 //Log.d(TAG, "found sensor: " + sensor.getName() + 600 // ", handle=" + sensor.getHandle()); 601 sensor.setLegacyType(getLegacySensorType(sensor.getType())); 602 fullList.add(sensor); 603 sHandleToSensor.append(sensor.getHandle(), sensor); 604 } 605 } while (i>0); 606 607 sSensorThread = new SensorThread(); 608 } 609 } 610 } 611 612 private int getLegacySensorType(int type) { 613 switch (type) { 614 case Sensor.TYPE_ACCELEROMETER: 615 return SENSOR_ACCELEROMETER; 616 case Sensor.TYPE_MAGNETIC_FIELD: 617 return SENSOR_MAGNETIC_FIELD; 618 case Sensor.TYPE_ORIENTATION: 619 return SENSOR_ORIENTATION_RAW; 620 case Sensor.TYPE_TEMPERATURE: 621 return SENSOR_TEMPERATURE; 622 } 623 return 0; 624 } 625 626 /** 627 * @return available sensors. 628 * @deprecated This method is deprecated, use 629 * {@link SensorManager#getSensorList(int)} instead 630 */ 631 @Deprecated 632 public int getSensors() { 633 int result = 0; 634 final ArrayList<Sensor> fullList = sFullSensorsList; 635 for (Sensor i : fullList) { 636 switch (i.getType()) { 637 case Sensor.TYPE_ACCELEROMETER: 638 result |= SensorManager.SENSOR_ACCELEROMETER; 639 break; 640 case Sensor.TYPE_MAGNETIC_FIELD: 641 result |= SensorManager.SENSOR_MAGNETIC_FIELD; 642 break; 643 case Sensor.TYPE_ORIENTATION: 644 result |= SensorManager.SENSOR_ORIENTATION | 645 SensorManager.SENSOR_ORIENTATION_RAW; 646 break; 647 } 648 } 649 return result; 650 } 651 652 /** 653 * Use this method to get the list of available sensors of a certain type. 654 * Make multiple calls to get sensors of different types or use 655 * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the 656 * sensors. 657 * 658 * @param type 659 * of sensors requested 660 * 661 * @return a list of sensors matching the asked type. 662 * 663 * @see #getDefaultSensor(int) 664 * @see Sensor 665 */ 666 public List<Sensor> getSensorList(int type) { 667 // cache the returned lists the first time 668 List<Sensor> list; 669 final ArrayList<Sensor> fullList = sFullSensorsList; 670 synchronized(fullList) { 671 list = sSensorListByType.get(type); 672 if (list == null) { 673 if (type == Sensor.TYPE_ALL) { 674 list = fullList; 675 } else { 676 list = new ArrayList<Sensor>(); 677 for (Sensor i : fullList) { 678 if (i.getType() == type) 679 list.add(i); 680 } 681 } 682 list = Collections.unmodifiableList(list); 683 sSensorListByType.append(type, list); 684 } 685 } 686 return list; 687 } 688 689 /** 690 * Use this method to get the default sensor for a given type. Note that the 691 * returned sensor could be a composite sensor, and its data could be 692 * averaged or filtered. If you need to access the raw sensors use 693 * {@link SensorManager#getSensorList(int) getSensorList}. 694 * 695 * @param type 696 * of sensors requested 697 * 698 * @return the default sensors matching the asked type. 699 * 700 * @see #getSensorList(int) 701 * @see Sensor 702 */ 703 public Sensor getDefaultSensor(int type) { 704 // TODO: need to be smarter, for now, just return the 1st sensor 705 List<Sensor> l = getSensorList(type); 706 return l.isEmpty() ? null : l.get(0); 707 } 708 709 /** 710 * Registers a listener for given sensors. 711 * 712 * @deprecated This method is deprecated, use 713 * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)} 714 * instead. 715 * 716 * @param listener 717 * sensor listener object 718 * 719 * @param sensors 720 * a bit masks of the sensors to register to 721 * 722 * @return <code>true</code> if the sensor is supported and successfully 723 * enabled 724 */ 725 @Deprecated 726 public boolean registerListener(SensorListener listener, int sensors) { 727 return registerListener(listener, sensors, SENSOR_DELAY_NORMAL); 728 } 729 730 /** 731 * Registers a SensorListener for given sensors. 732 * 733 * @deprecated This method is deprecated, use 734 * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)} 735 * instead. 736 * 737 * @param listener 738 * sensor listener object 739 * 740 * @param sensors 741 * a bit masks of the sensors to register to 742 * 743 * @param rate 744 * rate of events. This is only a hint to the system. events may be 745 * received faster or slower than the specified rate. Usually events 746 * are received faster. The value must be one of 747 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 748 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}. 749 * 750 * @return <code>true</code> if the sensor is supported and successfully 751 * enabled 752 */ 753 @Deprecated 754 public boolean registerListener(SensorListener listener, int sensors, int rate) { 755 if (listener == null) { 756 return false; 757 } 758 boolean result = false; 759 result = registerLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER, 760 listener, sensors, rate) || result; 761 result = registerLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD, 762 listener, sensors, rate) || result; 763 result = registerLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION, 764 listener, sensors, rate) || result; 765 result = registerLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION, 766 listener, sensors, rate) || result; 767 result = registerLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE, 768 listener, sensors, rate) || result; 769 return result; 770 } 771 772 @SuppressWarnings("deprecation") 773 private boolean registerLegacyListener(int legacyType, int type, 774 SensorListener listener, int sensors, int rate) 775 { 776 if (listener == null) { 777 return false; 778 } 779 boolean result = false; 780 // Are we activating this legacy sensor? 781 if ((sensors & legacyType) != 0) { 782 // if so, find a suitable Sensor 783 Sensor sensor = getDefaultSensor(type); 784 if (sensor != null) { 785 // If we don't already have one, create a LegacyListener 786 // to wrap this listener and process the events as 787 // they are expected by legacy apps. 788 LegacyListener legacyListener = null; 789 synchronized (mLegacyListenersMap) { 790 legacyListener = mLegacyListenersMap.get(listener); 791 if (legacyListener == null) { 792 // we didn't find a LegacyListener for this client, 793 // create one, and put it in our list. 794 legacyListener = new LegacyListener(listener); 795 mLegacyListenersMap.put(listener, legacyListener); 796 } 797 } 798 // register this legacy sensor with this legacy listener 799 legacyListener.registerSensor(legacyType); 800 // and finally, register the legacy listener with the new apis 801 result = registerListener(legacyListener, sensor, rate); 802 } 803 } 804 return result; 805 } 806 807 /** 808 * Unregisters a listener for the sensors with which it is registered. 809 * 810 * @deprecated This method is deprecated, use 811 * {@link SensorManager#unregisterListener(SensorEventListener, Sensor)} 812 * instead. 813 * 814 * @param listener 815 * a SensorListener object 816 * 817 * @param sensors 818 * a bit masks of the sensors to unregister from 819 */ 820 @Deprecated 821 public void unregisterListener(SensorListener listener, int sensors) { 822 unregisterLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER, 823 listener, sensors); 824 unregisterLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD, 825 listener, sensors); 826 unregisterLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION, 827 listener, sensors); 828 unregisterLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION, 829 listener, sensors); 830 unregisterLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE, 831 listener, sensors); 832 } 833 834 @SuppressWarnings("deprecation") 835 private void unregisterLegacyListener(int legacyType, int type, 836 SensorListener listener, int sensors) 837 { 838 if (listener == null) { 839 return; 840 } 841 // do we know about this listener? 842 LegacyListener legacyListener = null; 843 synchronized (mLegacyListenersMap) { 844 legacyListener = mLegacyListenersMap.get(listener); 845 } 846 if (legacyListener != null) { 847 // Are we deactivating this legacy sensor? 848 if ((sensors & legacyType) != 0) { 849 // if so, find the corresponding Sensor 850 Sensor sensor = getDefaultSensor(type); 851 if (sensor != null) { 852 // unregister this legacy sensor and if we don't 853 // need the corresponding Sensor, unregister it too 854 if (legacyListener.unregisterSensor(legacyType)) { 855 // corresponding sensor not needed, unregister 856 unregisterListener(legacyListener, sensor); 857 // finally check if we still need the legacyListener 858 // in our mapping, if not, get rid of it too. 859 synchronized(sListeners) { 860 boolean found = false; 861 for (ListenerDelegate i : sListeners) { 862 if (i.getListener() == legacyListener) { 863 found = true; 864 break; 865 } 866 } 867 if (!found) { 868 synchronized (mLegacyListenersMap) { 869 mLegacyListenersMap.remove(listener); 870 } 871 } 872 } 873 } 874 } 875 } 876 } 877 } 878 879 /** 880 * Unregisters a listener for all sensors. 881 * 882 * @deprecated This method is deprecated, use 883 * {@link SensorManager#unregisterListener(SensorEventListener)} 884 * instead. 885 * 886 * @param listener 887 * a SensorListener object 888 */ 889 @Deprecated 890 public void unregisterListener(SensorListener listener) { 891 unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW); 892 } 893 894 /** 895 * Unregisters a listener for the sensors with which it is registered. 896 * 897 * @param listener 898 * a SensorEventListener object 899 * 900 * @param sensor 901 * the sensor to unregister from 902 * 903 * @see #unregisterListener(SensorEventListener) 904 * @see #registerListener(SensorEventListener, Sensor, int) 905 * 906 */ 907 public void unregisterListener(SensorEventListener listener, Sensor sensor) { 908 unregisterListener((Object)listener, sensor); 909 } 910 911 /** 912 * Unregisters a listener for all sensors. 913 * 914 * @param listener 915 * a SensorListener object 916 * 917 * @see #unregisterListener(SensorEventListener, Sensor) 918 * @see #registerListener(SensorEventListener, Sensor, int) 919 * 920 */ 921 public void unregisterListener(SensorEventListener listener) { 922 unregisterListener((Object)listener); 923 } 924 925 /** 926 * Registers a {@link android.hardware.SensorEventListener 927 * SensorEventListener} for the given sensor. 928 * 929 * @param listener 930 * A {@link android.hardware.SensorEventListener SensorEventListener} 931 * object. 932 * 933 * @param sensor 934 * The {@link android.hardware.Sensor Sensor} to register to. 935 * 936 * @param rate 937 * The rate {@link android.hardware.SensorEvent sensor events} are 938 * delivered at. This is only a hint to the system. Events may be 939 * received faster or slower than the specified rate. Usually events 940 * are received faster. The value must be one of 941 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 942 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} 943 * or, the desired delay between events in microsecond. 944 * 945 * @return <code>true</code> if the sensor is supported and successfully 946 * enabled. 947 * 948 * @see #registerListener(SensorEventListener, Sensor, int, Handler) 949 * @see #unregisterListener(SensorEventListener) 950 * @see #unregisterListener(SensorEventListener, Sensor) 951 * 952 */ 953 public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) { 954 return registerListener(listener, sensor, rate, null); 955 } 956 957 /** 958 * Registers a {@link android.hardware.SensorEventListener 959 * SensorEventListener} for the given sensor. 960 * 961 * @param listener 962 * A {@link android.hardware.SensorEventListener SensorEventListener} 963 * object. 964 * 965 * @param sensor 966 * The {@link android.hardware.Sensor Sensor} to register to. 967 * 968 * @param rate 969 * The rate {@link android.hardware.SensorEvent sensor events} are 970 * delivered at. This is only a hint to the system. Events may be 971 * received faster or slower than the specified rate. Usually events 972 * are received faster. The value must be one of 973 * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, 974 * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}. 975 * or, the desired delay between events in microsecond. 976 * 977 * @param handler 978 * The {@link android.os.Handler Handler} the 979 * {@link android.hardware.SensorEvent sensor events} will be 980 * delivered to. 981 * 982 * @return true if the sensor is supported and successfully enabled. 983 * 984 * @see #registerListener(SensorEventListener, Sensor, int) 985 * @see #unregisterListener(SensorEventListener) 986 * @see #unregisterListener(SensorEventListener, Sensor) 987 * 988 */ 989 public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate, 990 Handler handler) { 991 if (listener == null || sensor == null) { 992 return false; 993 } 994 boolean result; 995 int delay = -1; 996 switch (rate) { 997 case SENSOR_DELAY_FASTEST: 998 delay = 0; 999 break; 1000 case SENSOR_DELAY_GAME: 1001 delay = 20000; 1002 break; 1003 case SENSOR_DELAY_UI: 1004 delay = 60000; 1005 break; 1006 case SENSOR_DELAY_NORMAL: 1007 delay = 200000; 1008 break; 1009 default: 1010 delay = rate; 1011 break; 1012 } 1013 1014 synchronized (sListeners) { 1015 ListenerDelegate l = null; 1016 for (ListenerDelegate i : sListeners) { 1017 if (i.getListener() == listener) { 1018 l = i; 1019 break; 1020 } 1021 } 1022 1023 String name = sensor.getName(); 1024 int handle = sensor.getHandle(); 1025 if (l == null) { 1026 result = false; 1027 l = new ListenerDelegate(listener, sensor, handler); 1028 sListeners.add(l); 1029 if (!sListeners.isEmpty()) { 1030 result = sSensorThread.startLocked(); 1031 if (result) { 1032 result = sensors_enable_sensor(sQueue, name, handle, delay); 1033 if (!result) { 1034 // there was an error, remove the listeners 1035 sListeners.remove(l); 1036 } 1037 } 1038 } 1039 } else { 1040 result = sensors_enable_sensor(sQueue, name, handle, delay); 1041 if (result) { 1042 l.addSensor(sensor); 1043 } 1044 } 1045 } 1046 return result; 1047 } 1048 1049 private void unregisterListener(Object listener, Sensor sensor) { 1050 if (listener == null || sensor == null) { 1051 return; 1052 } 1053 synchronized (sListeners) { 1054 final int size = sListeners.size(); 1055 for (int i=0 ; i<size ; i++) { 1056 ListenerDelegate l = sListeners.get(i); 1057 if (l.getListener() == listener) { 1058 // disable these sensors 1059 String name = sensor.getName(); 1060 int handle = sensor.getHandle(); 1061 sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE); 1062 // if we have no more sensors enabled on this listener, 1063 // take it off the list. 1064 if (l.removeSensor(sensor) == 0) { 1065 sListeners.remove(i); 1066 } 1067 break; 1068 } 1069 } 1070 } 1071 } 1072 1073 private void unregisterListener(Object listener) { 1074 if (listener == null) { 1075 return; 1076 } 1077 synchronized (sListeners) { 1078 final int size = sListeners.size(); 1079 for (int i=0 ; i<size ; i++) { 1080 ListenerDelegate l = sListeners.get(i); 1081 if (l.getListener() == listener) { 1082 // disable all sensors for this listener 1083 for (Sensor sensor : l.getSensors()) { 1084 String name = sensor.getName(); 1085 int handle = sensor.getHandle(); 1086 sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE); 1087 } 1088 sListeners.remove(i); 1089 break; 1090 } 1091 } 1092 } 1093 } 1094 1095 /** 1096 * <p> 1097 * Computes the inclination matrix <b>I</b> as well as the rotation matrix 1098 * <b>R</b> transforming a vector from the device coordinate system to the 1099 * world's coordinate system which is defined as a direct orthonormal basis, 1100 * where: 1101 * </p> 1102 * 1103 * <ul> 1104 * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to 1105 * the ground at the device's current location and roughly points East).</li> 1106 * <li>Y is tangential to the ground at the device's current location and 1107 * points towards the magnetic North Pole.</li> 1108 * <li>Z points towards the sky and is perpendicular to the ground.</li> 1109 * </ul> 1110 * 1111 * <p> 1112 * <center><img src="../../../images/axis_globe.png" 1113 * alt="Sensors coordinate-system diagram." border="0" /></center> 1114 * </p> 1115 * 1116 * <p> 1117 * <hr> 1118 * <p> 1119 * By definition: 1120 * <p> 1121 * [0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity) 1122 * <p> 1123 * [0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b> (m = magnitude of 1124 * geomagnetic field) 1125 * <p> 1126 * <b>R</b> is the identity matrix when the device is aligned with the 1127 * world's coordinate system, that is, when the device's X axis points 1128 * toward East, the Y axis points to the North Pole and the device is facing 1129 * the sky. 1130 * 1131 * <p> 1132 * <b>I</b> is a rotation matrix transforming the geomagnetic vector into 1133 * the same coordinate space as gravity (the world's coordinate space). 1134 * <b>I</b> is a simple rotation around the X axis. The inclination angle in 1135 * radians can be computed with {@link #getInclination}. 1136 * <hr> 1137 * 1138 * <p> 1139 * Each matrix is returned either as a 3x3 or 4x4 row-major matrix depending 1140 * on the length of the passed array: 1141 * <p> 1142 * <u>If the array length is 16:</u> 1143 * 1144 * <pre> 1145 * / M[ 0] M[ 1] M[ 2] M[ 3] \ 1146 * | M[ 4] M[ 5] M[ 6] M[ 7] | 1147 * | M[ 8] M[ 9] M[10] M[11] | 1148 * \ M[12] M[13] M[14] M[15] / 1149 *</pre> 1150 * 1151 * This matrix is ready to be used by OpenGL ES's 1152 * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int) 1153 * glLoadMatrixf(float[], int)}. 1154 * <p> 1155 * Note that because OpenGL matrices are column-major matrices you must 1156 * transpose the matrix before using it. However, since the matrix is a 1157 * rotation matrix, its transpose is also its inverse, conveniently, it is 1158 * often the inverse of the rotation that is needed for rendering; it can 1159 * therefore be used with OpenGL ES directly. 1160 * <p> 1161 * Also note that the returned matrices always have this form: 1162 * 1163 * <pre> 1164 * / M[ 0] M[ 1] M[ 2] 0 \ 1165 * | M[ 4] M[ 5] M[ 6] 0 | 1166 * | M[ 8] M[ 9] M[10] 0 | 1167 * \ 0 0 0 1 / 1168 *</pre> 1169 * 1170 * <p> 1171 * <u>If the array length is 9:</u> 1172 * 1173 * <pre> 1174 * / M[ 0] M[ 1] M[ 2] \ 1175 * | M[ 3] M[ 4] M[ 5] | 1176 * \ M[ 6] M[ 7] M[ 8] / 1177 *</pre> 1178 * 1179 * <hr> 1180 * <p> 1181 * The inverse of each matrix can be computed easily by taking its 1182 * transpose. 1183 * 1184 * <p> 1185 * The matrices returned by this function are meaningful only when the 1186 * device is not free-falling and it is not close to the magnetic north. If 1187 * the device is accelerating, or placed into a strong magnetic field, the 1188 * returned matrices may be inaccurate. 1189 * 1190 * @param R 1191 * is an array of 9 floats holding the rotation matrix <b>R</b> when 1192 * this function returns. R can be null. 1193 * <p> 1194 * 1195 * @param I 1196 * is an array of 9 floats holding the rotation matrix <b>I</b> when 1197 * this function returns. I can be null. 1198 * <p> 1199 * 1200 * @param gravity 1201 * is an array of 3 floats containing the gravity vector expressed in 1202 * the device's coordinate. You can simply use the 1203 * {@link android.hardware.SensorEvent#values values} returned by a 1204 * {@link android.hardware.SensorEvent SensorEvent} of a 1205 * {@link android.hardware.Sensor Sensor} of type 1206 * {@link android.hardware.Sensor#TYPE_ACCELEROMETER 1207 * TYPE_ACCELEROMETER}. 1208 * <p> 1209 * 1210 * @param geomagnetic 1211 * is an array of 3 floats containing the geomagnetic vector 1212 * expressed in the device's coordinate. You can simply use the 1213 * {@link android.hardware.SensorEvent#values values} returned by a 1214 * {@link android.hardware.SensorEvent SensorEvent} of a 1215 * {@link android.hardware.Sensor Sensor} of type 1216 * {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD 1217 * TYPE_MAGNETIC_FIELD}. 1218 * 1219 * @return <code>true</code> on success, <code>false</code> on failure (for 1220 * instance, if the device is in free fall). On failure the output 1221 * matrices are not modified. 1222 * 1223 * @see #getInclination(float[]) 1224 * @see #getOrientation(float[], float[]) 1225 * @see #remapCoordinateSystem(float[], int, int, float[]) 1226 */ 1227 1228 public static boolean getRotationMatrix(float[] R, float[] I, 1229 float[] gravity, float[] geomagnetic) { 1230 // TODO: move this to native code for efficiency 1231 float Ax = gravity[0]; 1232 float Ay = gravity[1]; 1233 float Az = gravity[2]; 1234 final float Ex = geomagnetic[0]; 1235 final float Ey = geomagnetic[1]; 1236 final float Ez = geomagnetic[2]; 1237 float Hx = Ey*Az - Ez*Ay; 1238 float Hy = Ez*Ax - Ex*Az; 1239 float Hz = Ex*Ay - Ey*Ax; 1240 final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz); 1241 if (normH < 0.1f) { 1242 // device is close to free fall (or in space?), or close to 1243 // magnetic north pole. Typical values are > 100. 1244 return false; 1245 } 1246 final float invH = 1.0f / normH; 1247 Hx *= invH; 1248 Hy *= invH; 1249 Hz *= invH; 1250 final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az); 1251 Ax *= invA; 1252 Ay *= invA; 1253 Az *= invA; 1254 final float Mx = Ay*Hz - Az*Hy; 1255 final float My = Az*Hx - Ax*Hz; 1256 final float Mz = Ax*Hy - Ay*Hx; 1257 if (R != null) { 1258 if (R.length == 9) { 1259 R[0] = Hx; R[1] = Hy; R[2] = Hz; 1260 R[3] = Mx; R[4] = My; R[5] = Mz; 1261 R[6] = Ax; R[7] = Ay; R[8] = Az; 1262 } else if (R.length == 16) { 1263 R[0] = Hx; R[1] = Hy; R[2] = Hz; R[3] = 0; 1264 R[4] = Mx; R[5] = My; R[6] = Mz; R[7] = 0; 1265 R[8] = Ax; R[9] = Ay; R[10] = Az; R[11] = 0; 1266 R[12] = 0; R[13] = 0; R[14] = 0; R[15] = 1; 1267 } 1268 } 1269 if (I != null) { 1270 // compute the inclination matrix by projecting the geomagnetic 1271 // vector onto the Z (gravity) and X (horizontal component 1272 // of geomagnetic vector) axes. 1273 final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez); 1274 final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE; 1275 final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE; 1276 if (I.length == 9) { 1277 I[0] = 1; I[1] = 0; I[2] = 0; 1278 I[3] = 0; I[4] = c; I[5] = s; 1279 I[6] = 0; I[7] =-s; I[8] = c; 1280 } else if (I.length == 16) { 1281 I[0] = 1; I[1] = 0; I[2] = 0; 1282 I[4] = 0; I[5] = c; I[6] = s; 1283 I[8] = 0; I[9] =-s; I[10]= c; 1284 I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0; 1285 I[15] = 1; 1286 } 1287 } 1288 return true; 1289 } 1290 1291 /** 1292 * Computes the geomagnetic inclination angle in radians from the 1293 * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}. 1294 * 1295 * @param I 1296 * inclination matrix see {@link #getRotationMatrix}. 1297 * 1298 * @return The geomagnetic inclination angle in radians. 1299 * 1300 * @see #getRotationMatrix(float[], float[], float[], float[]) 1301 * @see #getOrientation(float[], float[]) 1302 * @see GeomagneticField 1303 * 1304 */ 1305 public static float getInclination(float[] I) { 1306 if (I.length == 9) { 1307 return (float)Math.atan2(I[5], I[4]); 1308 } else { 1309 return (float)Math.atan2(I[6], I[5]); 1310 } 1311 } 1312 1313 /** 1314 * <p> 1315 * Rotates the supplied rotation matrix so it is expressed in a different 1316 * coordinate system. This is typically used when an application needs to 1317 * compute the three orientation angles of the device (see 1318 * {@link #getOrientation}) in a different coordinate system. 1319 * </p> 1320 * 1321 * <p> 1322 * When the rotation matrix is used for drawing (for instance with OpenGL 1323 * ES), it usually <b>doesn't need</b> to be transformed by this function, 1324 * unless the screen is physically rotated, in which case you can use 1325 * {@link android.view.Display#getRotation() Display.getRotation()} to 1326 * retrieve the current rotation of the screen. Note that because the user 1327 * is generally free to rotate their screen, you often should consider the 1328 * rotation in deciding the parameters to use here. 1329 * </p> 1330 * 1331 * <p> 1332 * <u>Examples:</u> 1333 * <p> 1334 * 1335 * <ul> 1336 * <li>Using the camera (Y axis along the camera's axis) for an augmented 1337 * reality application where the rotation angles are needed:</li> 1338 * 1339 * <p> 1340 * <ul> 1341 * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code> 1342 * </ul> 1343 * </p> 1344 * 1345 * <li>Using the device as a mechanical compass when rotation is 1346 * {@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:</li> 1347 * 1348 * <p> 1349 * <ul> 1350 * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code> 1351 * </ul> 1352 * </p> 1353 * 1354 * Beware of the above example. This call is needed only to account for a 1355 * rotation from its natural orientation when calculating the rotation 1356 * angles (see {@link #getOrientation}). If the rotation matrix is also used 1357 * for rendering, it may not need to be transformed, for instance if your 1358 * {@link android.app.Activity Activity} is running in landscape mode. 1359 * </ul> 1360 * 1361 * <p> 1362 * Since the resulting coordinate system is orthonormal, only two axes need 1363 * to be specified. 1364 * 1365 * @param inR 1366 * the rotation matrix to be transformed. Usually it is the matrix 1367 * returned by {@link #getRotationMatrix}. 1368 * 1369 * @param X 1370 * defines on which world axis and direction the X axis of the device 1371 * is mapped. 1372 * 1373 * @param Y 1374 * defines on which world axis and direction the Y axis of the device 1375 * is mapped. 1376 * 1377 * @param outR 1378 * the transformed rotation matrix. inR and outR can be the same 1379 * array, but it is not recommended for performance reason. 1380 * 1381 * @return <code>true</code> on success. <code>false</code> if the input 1382 * parameters are incorrect, for instance if X and Y define the same 1383 * axis. Or if inR and outR don't have the same length. 1384 * 1385 * @see #getRotationMatrix(float[], float[], float[], float[]) 1386 */ 1387 1388 public static boolean remapCoordinateSystem(float[] inR, int X, int Y, 1389 float[] outR) 1390 { 1391 if (inR == outR) { 1392 final float[] temp = mTempMatrix; 1393 synchronized(temp) { 1394 // we don't expect to have a lot of contention 1395 if (remapCoordinateSystemImpl(inR, X, Y, temp)) { 1396 final int size = outR.length; 1397 for (int i=0 ; i<size ; i++) 1398 outR[i] = temp[i]; 1399 return true; 1400 } 1401 } 1402 } 1403 return remapCoordinateSystemImpl(inR, X, Y, outR); 1404 } 1405 1406 private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y, 1407 float[] outR) 1408 { 1409 /* 1410 * X and Y define a rotation matrix 'r': 1411 * 1412 * (X==1)?((X&0x80)?-1:1):0 (X==2)?((X&0x80)?-1:1):0 (X==3)?((X&0x80)?-1:1):0 1413 * (Y==1)?((Y&0x80)?-1:1):0 (Y==2)?((Y&0x80)?-1:1):0 (Y==3)?((X&0x80)?-1:1):0 1414 * r[0] ^ r[1] 1415 * 1416 * where the 3rd line is the vector product of the first 2 lines 1417 * 1418 */ 1419 1420 final int length = outR.length; 1421 if (inR.length != length) 1422 return false; // invalid parameter 1423 if ((X & 0x7C)!=0 || (Y & 0x7C)!=0) 1424 return false; // invalid parameter 1425 if (((X & 0x3)==0) || ((Y & 0x3)==0)) 1426 return false; // no axis specified 1427 if ((X & 0x3) == (Y & 0x3)) 1428 return false; // same axis specified 1429 1430 // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y) 1431 // this can be calculated by exclusive-or'ing X and Y; except for 1432 // the sign inversion (+/-) which is calculated below. 1433 int Z = X ^ Y; 1434 1435 // extract the axis (remove the sign), offset in the range 0 to 2. 1436 final int x = (X & 0x3)-1; 1437 final int y = (Y & 0x3)-1; 1438 final int z = (Z & 0x3)-1; 1439 1440 // compute the sign of Z (whether it needs to be inverted) 1441 final int axis_y = (z+1)%3; 1442 final int axis_z = (z+2)%3; 1443 if (((x^axis_y)|(y^axis_z)) != 0) 1444 Z ^= 0x80; 1445 1446 final boolean sx = (X>=0x80); 1447 final boolean sy = (Y>=0x80); 1448 final boolean sz = (Z>=0x80); 1449 1450 // Perform R * r, in avoiding actual muls and adds. 1451 final int rowLength = ((length==16)?4:3); 1452 for (int j=0 ; j<3 ; j++) { 1453 final int offset = j*rowLength; 1454 for (int i=0 ; i<3 ; i++) { 1455 if (x==i) outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0]; 1456 if (y==i) outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1]; 1457 if (z==i) outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2]; 1458 } 1459 } 1460 if (length == 16) { 1461 outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0; 1462 outR[15] = 1; 1463 } 1464 return true; 1465 } 1466 1467 /** 1468 * Computes the device's orientation based on the rotation matrix. 1469 * <p> 1470 * When it returns, the array values is filled with the result: 1471 * <ul> 1472 * <li>values[0]: <i>azimuth</i>, rotation around the Z axis.</li> 1473 * <li>values[1]: <i>pitch</i>, rotation around the X axis.</li> 1474 * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li> 1475 * </ul> 1476 * <p> 1477 * <center><img src="../../../images/axis_device.png" 1478 * alt="Sensors coordinate-system diagram." border="0" /></center> 1479 * </p> 1480 * <p> 1481 * All three angles above are in <b>radians</b> and <b>positive</b> in the 1482 * <b>counter-clockwise</b> direction. 1483 * 1484 * @param R 1485 * rotation matrix see {@link #getRotationMatrix}. 1486 * 1487 * @param values 1488 * an array of 3 floats to hold the result. 1489 * 1490 * @return The array values passed as argument. 1491 * 1492 * @see #getRotationMatrix(float[], float[], float[], float[]) 1493 * @see GeomagneticField 1494 */ 1495 public static float[] getOrientation(float[] R, float values[]) { 1496 /* 1497 * 4x4 (length=16) case: 1498 * / R[ 0] R[ 1] R[ 2] 0 \ 1499 * | R[ 4] R[ 5] R[ 6] 0 | 1500 * | R[ 8] R[ 9] R[10] 0 | 1501 * \ 0 0 0 1 / 1502 * 1503 * 3x3 (length=9) case: 1504 * / R[ 0] R[ 1] R[ 2] \ 1505 * | R[ 3] R[ 4] R[ 5] | 1506 * \ R[ 6] R[ 7] R[ 8] / 1507 * 1508 */ 1509 if (R.length == 9) { 1510 values[0] = (float)Math.atan2(R[1], R[4]); 1511 values[1] = (float)Math.asin(-R[7]); 1512 values[2] = (float)Math.atan2(-R[6], R[8]); 1513 } else { 1514 values[0] = (float)Math.atan2(R[1], R[5]); 1515 values[1] = (float)Math.asin(-R[9]); 1516 values[2] = (float)Math.atan2(-R[8], R[10]); 1517 } 1518 return values; 1519 } 1520 1521 /** 1522 * Computes the Altitude in meters from the atmospheric pressure and the 1523 * pressure at sea level. 1524 * <p> 1525 * Typically the atmospheric pressure is read from a 1526 * {@link Sensor#TYPE_PRESSURE} sensor. The pressure at sea level must be 1527 * known, usually it can be retrieved from airport databases in the 1528 * vicinity. 1529 * </p> 1530 * 1531 * @param p0 pressure at sea level 1532 * @param p atmospheric pressure 1533 * @return Altitude in meters 1534 */ 1535 public static float getAltitude(float p0, float p) { 1536 final float coef = 1.0f / 5.255f; 1537 return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef)); 1538 } 1539 1540 1541 /** 1542 * {@hide} 1543 */ 1544 public void onRotationChanged(int rotation) { 1545 synchronized(sListeners) { 1546 sRotation = rotation; 1547 } 1548 } 1549 1550 static int getRotation() { 1551 synchronized(sListeners) { 1552 return sRotation; 1553 } 1554 } 1555 1556 private class LegacyListener implements SensorEventListener { 1557 private float mValues[] = new float[6]; 1558 @SuppressWarnings("deprecation") 1559 private SensorListener mTarget; 1560 private int mSensors; 1561 private final LmsFilter mYawfilter = new LmsFilter(); 1562 1563 @SuppressWarnings("deprecation") 1564 LegacyListener(SensorListener target) { 1565 mTarget = target; 1566 mSensors = 0; 1567 } 1568 1569 void registerSensor(int legacyType) { 1570 mSensors |= legacyType; 1571 } 1572 1573 boolean unregisterSensor(int legacyType) { 1574 mSensors &= ~legacyType; 1575 int mask = SENSOR_ORIENTATION|SENSOR_ORIENTATION_RAW; 1576 if (((legacyType&mask)!=0) && ((mSensors&mask)!=0)) { 1577 return false; 1578 } 1579 return true; 1580 } 1581 1582 @SuppressWarnings("deprecation") 1583 public void onAccuracyChanged(Sensor sensor, int accuracy) { 1584 try { 1585 mTarget.onAccuracyChanged(sensor.getLegacyType(), accuracy); 1586 } catch (AbstractMethodError e) { 1587 // old app that doesn't implement this method 1588 // just ignore it. 1589 } 1590 } 1591 1592 @SuppressWarnings("deprecation") 1593 public void onSensorChanged(SensorEvent event) { 1594 final float v[] = mValues; 1595 v[0] = event.values[0]; 1596 v[1] = event.values[1]; 1597 v[2] = event.values[2]; 1598 int legacyType = event.sensor.getLegacyType(); 1599 mapSensorDataToWindow(legacyType, v, SensorManager.getRotation()); 1600 if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) { 1601 if ((mSensors & SENSOR_ORIENTATION_RAW)!=0) { 1602 mTarget.onSensorChanged(SENSOR_ORIENTATION_RAW, v); 1603 } 1604 if ((mSensors & SENSOR_ORIENTATION)!=0) { 1605 v[0] = mYawfilter.filter(event.timestamp, v[0]); 1606 mTarget.onSensorChanged(SENSOR_ORIENTATION, v); 1607 } 1608 } else { 1609 mTarget.onSensorChanged(legacyType, v); 1610 } 1611 } 1612 1613 /* 1614 * Helper function to convert the specified sensor's data to the windows's 1615 * coordinate space from the device's coordinate space. 1616 * 1617 * output: 3,4,5: values in the old API format 1618 * 0,1,2: transformed values in the old API format 1619 * 1620 */ 1621 private void mapSensorDataToWindow(int sensor, 1622 float[] values, int orientation) { 1623 float x = values[0]; 1624 float y = values[1]; 1625 float z = values[2]; 1626 1627 switch (sensor) { 1628 case SensorManager.SENSOR_ORIENTATION: 1629 case SensorManager.SENSOR_ORIENTATION_RAW: 1630 z = -z; 1631 break; 1632 case SensorManager.SENSOR_ACCELEROMETER: 1633 x = -x; 1634 y = -y; 1635 z = -z; 1636 break; 1637 case SensorManager.SENSOR_MAGNETIC_FIELD: 1638 x = -x; 1639 y = -y; 1640 break; 1641 } 1642 values[0] = x; 1643 values[1] = y; 1644 values[2] = z; 1645 values[3] = x; 1646 values[4] = y; 1647 values[5] = z; 1648 1649 if ((orientation & Surface.ROTATION_90) != 0) { 1650 // handles 90 and 270 rotation 1651 switch (sensor) { 1652 case SENSOR_ACCELEROMETER: 1653 case SENSOR_MAGNETIC_FIELD: 1654 values[0] =-y; 1655 values[1] = x; 1656 values[2] = z; 1657 break; 1658 case SENSOR_ORIENTATION: 1659 case SENSOR_ORIENTATION_RAW: 1660 values[0] = x + ((x < 270) ? 90 : -270); 1661 values[1] = z; 1662 values[2] = y; 1663 break; 1664 } 1665 } 1666 if ((orientation & Surface.ROTATION_180) != 0) { 1667 x = values[0]; 1668 y = values[1]; 1669 z = values[2]; 1670 // handles 180 (flip) and 270 (flip + 90) rotation 1671 switch (sensor) { 1672 case SENSOR_ACCELEROMETER: 1673 case SENSOR_MAGNETIC_FIELD: 1674 values[0] =-x; 1675 values[1] =-y; 1676 values[2] = z; 1677 break; 1678 case SENSOR_ORIENTATION: 1679 case SENSOR_ORIENTATION_RAW: 1680 values[0] = (x >= 180) ? (x - 180) : (x + 180); 1681 values[1] =-y; 1682 values[2] =-z; 1683 break; 1684 } 1685 } 1686 } 1687 } 1688 1689 class LmsFilter { 1690 private static final int SENSORS_RATE_MS = 20; 1691 private static final int COUNT = 12; 1692 private static final float PREDICTION_RATIO = 1.0f/3.0f; 1693 private static final float PREDICTION_TIME = (SENSORS_RATE_MS*COUNT/1000.0f)*PREDICTION_RATIO; 1694 private float mV[] = new float[COUNT*2]; 1695 private float mT[] = new float[COUNT*2]; 1696 private int mIndex; 1697 1698 public LmsFilter() { 1699 mIndex = COUNT; 1700 } 1701 1702 public float filter(long time, float in) { 1703 float v = in; 1704 final float ns = 1.0f / 1000000000.0f; 1705 final float t = time*ns; 1706 float v1 = mV[mIndex]; 1707 if ((v-v1) > 180) { 1708 v -= 360; 1709 } else if ((v1-v) > 180) { 1710 v += 360; 1711 } 1712 /* Manage the circular buffer, we write the data twice spaced 1713 * by COUNT values, so that we don't have to copy the array 1714 * when it's full 1715 */ 1716 mIndex++; 1717 if (mIndex >= COUNT*2) 1718 mIndex = COUNT; 1719 mV[mIndex] = v; 1720 mT[mIndex] = t; 1721 mV[mIndex-COUNT] = v; 1722 mT[mIndex-COUNT] = t; 1723 1724 float A, B, C, D, E; 1725 float a, b; 1726 int i; 1727 1728 A = B = C = D = E = 0; 1729 for (i=0 ; i<COUNT-1 ; i++) { 1730 final int j = mIndex - 1 - i; 1731 final float Z = mV[j]; 1732 final float T = 0.5f*(mT[j] + mT[j+1]) - t; 1733 float dT = mT[j] - mT[j+1]; 1734 dT *= dT; 1735 A += Z*dT; 1736 B += T*(T*dT); 1737 C += (T*dT); 1738 D += Z*(T*dT); 1739 E += dT; 1740 } 1741 b = (A*B + C*D) / (E*B + C*C); 1742 a = (E*b - A) / C; 1743 float f = b + PREDICTION_TIME*a; 1744 1745 // Normalize 1746 f *= (1.0f / 360.0f); 1747 if (((f>=0)?f:-f) >= 0.5f) 1748 f = f - (float)Math.ceil(f + 0.5f) + 1.0f; 1749 if (f < 0) 1750 f += 1.0f; 1751 f *= 360.0f; 1752 return f; 1753 } 1754 } 1755 1756 1757 private static native void nativeClassInit(); 1758 1759 private static native int sensors_module_init(); 1760 private static native int sensors_module_get_next_sensor(Sensor sensor, int next); 1761 1762 // Used within this module from outside SensorManager, don't make private 1763 static native int sensors_create_queue(); 1764 static native void sensors_destroy_queue(int queue); 1765 static native boolean sensors_enable_sensor(int queue, String name, int sensor, int enable); 1766 static native int sensors_data_poll(int queue, float[] values, int[] status, long[] timestamp); 1767} 1768