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