diff options
| -rwxr-xr-x | core/java/android/webkit/DeviceMotionService.java | 170 | ||||
| -rw-r--r-- | core/java/android/webkit/DeviceOrientationManager.java | 12 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewCore.java | 10 |
3 files changed, 191 insertions, 1 deletions
diff --git a/core/java/android/webkit/DeviceMotionService.java b/core/java/android/webkit/DeviceMotionService.java new file mode 100755 index 000000000000..4027c26839a2 --- /dev/null +++ b/core/java/android/webkit/DeviceMotionService.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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.os.Message; +import android.webkit.DeviceOrientationManager; +import java.lang.Runnable; +import java.util.List; + + +final class DeviceMotionService implements SensorEventListener { + private DeviceOrientationManager mManager; + private boolean mIsRunning; + private Handler mHandler; + private SensorManager mSensorManager; + private Context mContext; + private boolean mHaveSentErrorEvent; + private Runnable mUpdateRunnable; + private float mLastAcceleration[]; + + private static final int INTERVAL_MILLIS = 100; + + public DeviceMotionService(DeviceOrientationManager manager, Context context) { + mManager = manager; + assert(mManager != null); + mContext = context; + assert(mContext != null); + } + + public void start() { + mIsRunning = true; + registerForSensor(); + } + + public void stop() { + mIsRunning = false; + stopSendingUpdates(); + unregisterFromSensor(); + } + + public void suspend() { + if (mIsRunning) { + stopSendingUpdates(); + unregisterFromSensor(); + } + } + + public void resume() { + if (mIsRunning) { + registerForSensor(); + } + } + + private void sendErrorEvent() { + assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); + // The spec requires that each listener receives the error event only once. + if (mHaveSentErrorEvent) + return; + mHaveSentErrorEvent = true; + createHandler(); + mHandler.post(new Runnable() { + @Override + public void run() { + assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); + if (mIsRunning) { + // The special case of all nulls is used to signify a failure to get data. + mManager.onMotionChange(null, null, null, 0.0); + } + } + }); + } + + private void createHandler() { + if (mHandler != null) { + return; + } + + mHandler = new Handler(); + mUpdateRunnable = new Runnable() { + @Override + public void run() { + mManager.onMotionChange(new Double(mLastAcceleration[0]), + new Double(mLastAcceleration[1]), new Double(mLastAcceleration[2]), + INTERVAL_MILLIS); + mHandler.postDelayed(mUpdateRunnable, INTERVAL_MILLIS); + // Now that we have successfully sent some data, reset whether we've sent an error. + mHaveSentErrorEvent = false; + } + }; + } + + private void startSendingUpdates() { + createHandler(); + mUpdateRunnable.run(); + } + + private void stopSendingUpdates() { + mHandler.removeCallbacks(mUpdateRunnable); + mLastAcceleration = null; + } + + private void registerForSensor() { + if (!registerForAccelerometerSensor()) { + sendErrorEvent(); + } + } + + 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; + } + createHandler(); + // TODO: Consider handling multiple sensors. + return getSensorManager().registerListener( + this, sensors.get(0), SensorManager.SENSOR_DELAY_UI, mHandler); + } + + private void unregisterFromSensor() { + getSensorManager().unregisterListener(this); + } + + /** + * 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()); + assert(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER); + + boolean firstData = mLastAcceleration == null; + mLastAcceleration = event.values; + if (firstData) { + startSendingUpdates(); + } + } + + public void onAccuracyChanged(Sensor sensor, int accuracy) { + assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); + } +} diff --git a/core/java/android/webkit/DeviceOrientationManager.java b/core/java/android/webkit/DeviceOrientationManager.java index aac2f43a2b89..2076a9e72ee0 100644 --- a/core/java/android/webkit/DeviceOrientationManager.java +++ b/core/java/android/webkit/DeviceOrientationManager.java @@ -26,7 +26,6 @@ package android.webkit; */ public final class DeviceOrientationManager { private WebViewCore mWebViewCore; - private DeviceOrientationService mService; public DeviceOrientationManager(WebViewCore webViewCore) { mWebViewCore = webViewCore; @@ -51,6 +50,14 @@ public final class DeviceOrientationManager { canProvideGamma, gamma); } + // We only provide accelerationIncludingGravity. + public void onMotionChange(Double x, Double y, Double z, double interval) { + nativeOnMotionChange(mWebViewCore, + x != null, x != null ? x.doubleValue() : 0.0, + y != null, y != null ? y.doubleValue() : 0.0, + z != null, z != null ? z.doubleValue() : 0.0, + interval); + } public void onOrientationChange(Double alpha, Double beta, Double gamma) { nativeOnOrientationChange(mWebViewCore, alpha != null, alpha != null ? alpha.doubleValue() : 0.0, @@ -63,6 +70,9 @@ public final class DeviceOrientationManager { private static native void nativeSetMockOrientation(WebViewCore webViewCore, boolean canProvideAlpha, double alpha, boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma); + private static native void nativeOnMotionChange(WebViewCore webViewCore, + boolean canProvideX, double x, boolean canProvideY, double y, + boolean canProvideZ, double z, double interval); private static native void nativeOnOrientationChange(WebViewCore webViewCore, boolean canProvideAlpha, double alpha, boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma); diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 7c089d8500ac..73ead27227d7 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -34,6 +34,7 @@ import android.util.SparseBooleanArray; import android.view.KeyEvent; import android.view.SurfaceView; import android.view.View; +import android.webkit.DeviceMotionService; import android.webkit.DeviceOrientationManager; import android.webkit.DeviceOrientationService; @@ -120,6 +121,7 @@ final class WebViewCore { private int mWebkitScrollY = 0; private DeviceOrientationManager mDeviceOrientationManager = new DeviceOrientationManager(this); + private DeviceMotionService mDeviceMotionService; private DeviceOrientationService mDeviceOrientationService; // The thread name used to identify the WebCore thread and for use in @@ -2553,6 +2555,14 @@ final class WebViewCore { canProvideGamma, gamma); } + protected DeviceMotionService getDeviceMotionService() { + if (mDeviceMotionService == null) { + mDeviceMotionService = + new DeviceMotionService(mDeviceOrientationManager, mContext); + } + return mDeviceMotionService; + } + protected DeviceOrientationService getDeviceOrientationService() { if (mDeviceOrientationService == null) { mDeviceOrientationService = |