1dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block/* 2dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * Copyright (C) 2010 The Android Open Source Project 3dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * 4dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * Licensed under the Apache License, Version 2.0 (the "License"); 5dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * you may not use this file except in compliance with the License. 6dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * You may obtain a copy of the License at 7dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * 8dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * http://www.apache.org/licenses/LICENSE-2.0 9dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * 10dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * Unless required by applicable law or agreed to in writing, software 11dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * distributed under the License is distributed on an "AS IS" BASIS, 12dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * See the License for the specific language governing permissions and 14dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * limitations under the License. 15dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block */ 16dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 17dc82a29b1108622694fb9f1036e2225eafac58c1Steve Blockpackage android.webkit; 18dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 19dc82a29b1108622694fb9f1036e2225eafac58c1Steve Blockimport android.content.Context; 20dc82a29b1108622694fb9f1036e2225eafac58c1Steve Blockimport android.hardware.Sensor; 21dc82a29b1108622694fb9f1036e2225eafac58c1Steve Blockimport android.hardware.SensorEvent; 22dc82a29b1108622694fb9f1036e2225eafac58c1Steve Blockimport android.hardware.SensorEventListener; 23dc82a29b1108622694fb9f1036e2225eafac58c1Steve Blockimport android.hardware.SensorManager; 24dc82a29b1108622694fb9f1036e2225eafac58c1Steve Blockimport android.os.Handler; 25dc82a29b1108622694fb9f1036e2225eafac58c1Steve Blockimport android.os.Message; 261be73390778eb1b033a4db6339c8a8b325dfaad9Steve Blockimport android.webkit.DeviceMotionAndOrientationManager; 27dc82a29b1108622694fb9f1036e2225eafac58c1Steve Blockimport java.lang.Runnable; 28dc82a29b1108622694fb9f1036e2225eafac58c1Steve Blockimport java.util.List; 29dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 30dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 31dc82a29b1108622694fb9f1036e2225eafac58c1Steve Blockfinal class DeviceMotionService implements SensorEventListener { 321be73390778eb1b033a4db6339c8a8b325dfaad9Steve Block private DeviceMotionAndOrientationManager mManager; 33dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private boolean mIsRunning; 34dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private Handler mHandler; 35dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private SensorManager mSensorManager; 36dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private Context mContext; 37dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private boolean mHaveSentErrorEvent; 38dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private Runnable mUpdateRunnable; 39dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private float mLastAcceleration[]; 40dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 41dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private static final int INTERVAL_MILLIS = 100; 42dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 431be73390778eb1b033a4db6339c8a8b325dfaad9Steve Block public DeviceMotionService(DeviceMotionAndOrientationManager manager, Context context) { 44dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mManager = manager; 45dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block assert(mManager != null); 46dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mContext = context; 47dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block assert(mContext != null); 48dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 49dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 50dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block public void start() { 51dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mIsRunning = true; 52dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block registerForSensor(); 53dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 54dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 55dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block public void stop() { 56dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mIsRunning = false; 57dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block stopSendingUpdates(); 58dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block unregisterFromSensor(); 59dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 60dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 61dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block public void suspend() { 62dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block if (mIsRunning) { 63dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block stopSendingUpdates(); 64dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block unregisterFromSensor(); 65dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 66dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 67dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 68dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block public void resume() { 69dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block if (mIsRunning) { 70dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block registerForSensor(); 71dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 72dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 73dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 74dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private void sendErrorEvent() { 75dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); 76dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block // The spec requires that each listener receives the error event only once. 77dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block if (mHaveSentErrorEvent) 78dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block return; 79dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mHaveSentErrorEvent = true; 80dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block createHandler(); 81dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mHandler.post(new Runnable() { 82dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block @Override 83dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block public void run() { 84dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); 85dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block if (mIsRunning) { 86dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block // The special case of all nulls is used to signify a failure to get data. 87dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mManager.onMotionChange(null, null, null, 0.0); 88dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 89dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 90dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block }); 91dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 92dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 93dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private void createHandler() { 94dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block if (mHandler != null) { 95dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block return; 96dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 97dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 98dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mHandler = new Handler(); 99dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mUpdateRunnable = new Runnable() { 100dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block @Override 101dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block public void run() { 102d09001fea476ca6c6eaff5e29a1bb6f3aebe5bd5Steve Block assert mIsRunning; 103dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mManager.onMotionChange(new Double(mLastAcceleration[0]), 104dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block new Double(mLastAcceleration[1]), new Double(mLastAcceleration[2]), 105dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block INTERVAL_MILLIS); 106dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mHandler.postDelayed(mUpdateRunnable, INTERVAL_MILLIS); 107dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block // Now that we have successfully sent some data, reset whether we've sent an error. 108dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mHaveSentErrorEvent = false; 109dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 110dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block }; 111dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 112dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 113dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private void startSendingUpdates() { 114dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block createHandler(); 115dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mUpdateRunnable.run(); 116dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 117dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 118dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private void stopSendingUpdates() { 119dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mHandler.removeCallbacks(mUpdateRunnable); 120dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mLastAcceleration = null; 121dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 122dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 123dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private void registerForSensor() { 124dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block if (!registerForAccelerometerSensor()) { 125dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block sendErrorEvent(); 126dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 127dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 128dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 129dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private SensorManager getSensorManager() { 130dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); 131dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block if (mSensorManager == null) { 132dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); 133dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 134dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block return mSensorManager; 135dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 136dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 137dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private boolean registerForAccelerometerSensor() { 138dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block List<Sensor> sensors = getSensorManager().getSensorList(Sensor.TYPE_ACCELEROMETER); 139dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block if (sensors.isEmpty()) { 140dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block return false; 141dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 142dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block createHandler(); 143dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block // TODO: Consider handling multiple sensors. 144dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block return getSensorManager().registerListener( 145dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block this, sensors.get(0), SensorManager.SENSOR_DELAY_UI, mHandler); 146dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 147dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 148dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block private void unregisterFromSensor() { 149dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block getSensorManager().unregisterListener(this); 150dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 151dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 152dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block /** 153dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * SensorEventListener implementation. 154dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block * Callbacks happen on the thread on which we registered - the WebCore thread. 155dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block */ 1565ba2efeb9faaf7db9da205102b9a7f40b4b89f27Steve Block @Override 157dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block public void onSensorChanged(SensorEvent event) { 158dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block assert(event.values.length == 3); 159dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); 160dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block assert(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER); 161dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 162d09001fea476ca6c6eaff5e29a1bb6f3aebe5bd5Steve Block // We may get callbacks after the call to getSensorManager().unregisterListener() returns. 163d09001fea476ca6c6eaff5e29a1bb6f3aebe5bd5Steve Block if (!mIsRunning) { 164d09001fea476ca6c6eaff5e29a1bb6f3aebe5bd5Steve Block return; 165d09001fea476ca6c6eaff5e29a1bb6f3aebe5bd5Steve Block } 166d09001fea476ca6c6eaff5e29a1bb6f3aebe5bd5Steve Block 167dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block boolean firstData = mLastAcceleration == null; 168dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block mLastAcceleration = event.values; 169dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block if (firstData) { 170dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block startSendingUpdates(); 171dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 172dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 173dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block 1745ba2efeb9faaf7db9da205102b9a7f40b4b89f27Steve Block @Override 175dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block public void onAccuracyChanged(Sensor sensor, int accuracy) { 176dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); 177dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block } 178dc82a29b1108622694fb9f1036e2225eafac58c1Steve Block} 179