Merge "Hook up device sensors for DeviceOrientation"
This commit is contained in:
@@ -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;
|
||||
|
||||
public DeviceOrientationService(DeviceOrientationManager manager) {
|
||||
private static final double DELTA_DEGRESS = 1.0;
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2504,7 +2504,8 @@ final class WebViewCore {
|
||||
|
||||
protected DeviceOrientationService getDeviceOrientationService() {
|
||||
if (mDeviceOrientationService == null) {
|
||||
mDeviceOrientationService = new DeviceOrientationService(mDeviceOrientationManager);
|
||||
mDeviceOrientationService =
|
||||
new DeviceOrientationService(mDeviceOrientationManager, mContext);
|
||||
}
|
||||
return mDeviceOrientationService;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user