diff options
| author | Steve Block <steveblock@google.com> | 2010-08-18 11:12:07 +0100 |
|---|---|---|
| committer | Steve Block <steveblock@google.com> | 2010-08-24 16:33:46 +0100 |
| commit | bb9db22fbb264f9a31ab85f74339b94cb1ab7151 (patch) | |
| tree | 71ea9ef2eff989963d894200fd90f0c67b48e02f /core/java/android/webkit/DeviceOrientationService.java | |
| parent | 41d5e93bbdff5dc6383ebd9391e3f1c492dee215 (diff) | |
Hook up device sensors for DeviceOrientation
Change-Id: Ic7165a07a02e3c38165b2f92e3ec7368d2b60e19
Diffstat (limited to 'core/java/android/webkit/DeviceOrientationService.java')
| -rwxr-xr-x | core/java/android/webkit/DeviceOrientationService.java | 151 |
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()); } } |
