Loading core/java/android/webkit/DeviceOrientationService.java +142 −9 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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() { Loading @@ -70,12 +87,128 @@ final class DeviceOrientationService { } private void registerForSensors() { // Send the error event for now. // FIXME: Implement. 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()); } } core/java/android/webkit/WebViewCore.java +2 −1 Original line number Diff line number Diff line Loading @@ -2504,7 +2504,8 @@ final class WebViewCore { protected DeviceOrientationService getDeviceOrientationService() { if (mDeviceOrientationService == null) { mDeviceOrientationService = new DeviceOrientationService(mDeviceOrientationManager); mDeviceOrientationService = new DeviceOrientationService(mDeviceOrientationManager, mContext); } return mDeviceOrientationService; } Loading Loading
core/java/android/webkit/DeviceOrientationService.java +142 −9 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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() { Loading @@ -70,12 +87,128 @@ final class DeviceOrientationService { } private void registerForSensors() { // Send the error event for now. // FIXME: Implement. 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()); } }
core/java/android/webkit/WebViewCore.java +2 −1 Original line number Diff line number Diff line Loading @@ -2504,7 +2504,8 @@ final class WebViewCore { protected DeviceOrientationService getDeviceOrientationService() { if (mDeviceOrientationService == null) { mDeviceOrientationService = new DeviceOrientationService(mDeviceOrientationManager); mDeviceOrientationService = new DeviceOrientationService(mDeviceOrientationManager, mContext); } return mDeviceOrientationService; } Loading