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