summaryrefslogtreecommitdiff
path: root/core/java/android/webkit/DeviceOrientationService.java
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-08-18 11:12:07 +0100
committerSteve Block <steveblock@google.com>2010-08-24 16:33:46 +0100
commitbb9db22fbb264f9a31ab85f74339b94cb1ab7151 (patch)
tree71ea9ef2eff989963d894200fd90f0c67b48e02f /core/java/android/webkit/DeviceOrientationService.java
parent41d5e93bbdff5dc6383ebd9391e3f1c492dee215 (diff)
Hook up device sensors for DeviceOrientation
Change-Id: Ic7165a07a02e3c38165b2f92e3ec7368d2b60e19
Diffstat (limited to 'core/java/android/webkit/DeviceOrientationService.java')
-rwxr-xr-xcore/java/android/webkit/DeviceOrientationService.java151
1 files changed, 142 insertions, 9 deletions
diff --git a/core/java/android/webkit/DeviceOrientationService.java b/core/java/android/webkit/DeviceOrientationService.java
index 07d3d2fedf82..4ff849ea0162 100755
--- a/core/java/android/webkit/DeviceOrientationService.java
+++ b/core/java/android/webkit/DeviceOrientationService.java
@@ -16,19 +16,39 @@
package android.webkit;
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
import android.os.Handler;
import android.webkit.DeviceOrientationManager;
import java.lang.Runnable;
+import java.util.List;
-final class DeviceOrientationService {
+final class DeviceOrientationService implements SensorEventListener {
+ // The gravity vector expressed in the body frame.
+ private float[] mGravityVector;
+ // The geomagnetic vector expressed in the body frame.
+ private float[] mMagneticFieldVector;
+
private DeviceOrientationManager mManager;
private boolean mIsRunning;
private Handler mHandler;
+ private SensorManager mSensorManager;
+ private Context mContext;
+ private Double mAlpha;
+ private Double mBeta;
+ private Double mGamma;
+
+ private static final double DELTA_DEGRESS = 1.0;
- public DeviceOrientationService(DeviceOrientationManager manager) {
+ public DeviceOrientationService(DeviceOrientationManager manager, Context context) {
mManager = manager;
assert(mManager != null);
+ mContext = context;
+ assert(mContext != null);
}
public void start() {
@@ -55,9 +75,6 @@ final class DeviceOrientationService {
private void sendErrorEvent() {
assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
- if (mHandler == null) {
- mHandler = new Handler();
- }
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -70,12 +87,128 @@ final class DeviceOrientationService {
}
private void registerForSensors() {
- // Send the error event for now.
- // FIXME: Implement.
- sendErrorEvent();
+ if (mHandler == null) {
+ mHandler = new Handler();
+ }
+ if (!registerForAccelerometerSensor() || !registerForMagneticFieldSensor()) {
+ unregisterFromSensors();
+ sendErrorEvent();
+ }
+ }
+
+ private void getOrientationUsingGetRotationMatrix() {
+ if (mGravityVector == null || mMagneticFieldVector == null) {
+ return;
+ }
+
+ // Get the rotation matrix.
+ // The rotation matrix that transforms from the body frame to the earth frame.
+ float[] deviceRotationMatrix = new float[9];
+ if (!SensorManager.getRotationMatrix(
+ deviceRotationMatrix, null, mGravityVector, mMagneticFieldVector)) {
+ return;
+ }
+
+ // Convert rotation matrix to rotation angles.
+ // Assuming that the rotations are appied in the order listed at
+ // http://developer.android.com/reference/android/hardware/SensorEvent.html#values
+ // the rotations are applied about the same axes and in the same order as required by the
+ // API. The only conversions are sign changes as follows.
+ // The angles are in radians
+ float[] rotationAngles = new float[3];
+ SensorManager.getOrientation(deviceRotationMatrix, rotationAngles);
+ double alpha = Math.toDegrees(-rotationAngles[0]) - 90.0;
+ while (alpha < 0.0) { alpha += 360.0; } // [0, 360)
+ double beta = Math.toDegrees(-rotationAngles[1]);
+ while (beta < -180.0) { beta += 360.0; } // [-180, 180)
+ double gamma = Math.toDegrees(rotationAngles[2]);
+ while (gamma < -90.0) { gamma += 360.0; } // [-90, 90)
+
+ maybeSendChange(alpha, beta, gamma);
+ }
+
+ private SensorManager getSensorManager() {
+ assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
+ if (mSensorManager == null) {
+ mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+ }
+ return mSensorManager;
+ }
+
+ private boolean registerForAccelerometerSensor() {
+ List<Sensor> sensors = getSensorManager().getSensorList(Sensor.TYPE_ACCELEROMETER);
+ if (sensors.isEmpty()) {
+ return false;
+ }
+ // TODO: Consider handling multiple sensors.
+ return getSensorManager().registerListener(
+ this, sensors.get(0), SensorManager.SENSOR_DELAY_FASTEST, mHandler);
+ }
+
+ private boolean registerForMagneticFieldSensor() {
+ List<Sensor> sensors = getSensorManager().getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
+ if (sensors.isEmpty()) {
+ return false;
+ }
+ // TODO: Consider handling multiple sensors.
+ return getSensorManager().registerListener(
+ this, sensors.get(0), SensorManager.SENSOR_DELAY_FASTEST, mHandler);
}
private void unregisterFromSensors() {
- // FIXME: Implement.
+ getSensorManager().unregisterListener(this);
+ }
+
+ private void maybeSendChange(double alpha, double beta, double gamma) {
+ assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
+ if (mAlpha == null || mBeta == null || mGamma == null
+ || Math.abs(alpha - mAlpha) > DELTA_DEGRESS
+ || Math.abs(beta - mBeta) > DELTA_DEGRESS
+ || Math.abs(gamma - mGamma) > DELTA_DEGRESS) {
+ mAlpha = alpha;
+ mBeta = beta;
+ mGamma = gamma;
+ mManager.onOrientationChange(mAlpha, mBeta, mGamma);
+ }
+ }
+
+ /**
+ * SensorEventListener implementation.
+ * Callbacks happen on the thread on which we registered - the WebCore thread.
+ */
+ public void onSensorChanged(SensorEvent event) {
+ assert(event.values.length == 3);
+ assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
+
+ if (!mIsRunning) {
+ return;
+ }
+
+ switch (event.sensor.getType()) {
+ case Sensor.TYPE_ACCELEROMETER:
+ if (mGravityVector == null) {
+ mGravityVector = new float[3];
+ }
+ mGravityVector[0] = event.values[0];
+ mGravityVector[1] = event.values[1];
+ mGravityVector[2] = event.values[2];
+ getOrientationUsingGetRotationMatrix();
+ break;
+ case Sensor.TYPE_MAGNETIC_FIELD:
+ if (mMagneticFieldVector == null) {
+ mMagneticFieldVector = new float[3];
+ }
+ mMagneticFieldVector[0] = event.values[0];
+ mMagneticFieldVector[1] = event.values[1];
+ mMagneticFieldVector[2] = event.values[2];
+ getOrientationUsingGetRotationMatrix();
+ break;
+ default:
+ assert(false);
+ }
+ }
+
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
}
}