|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* Copyright 2012 Mozilla Foundation and Mozilla contributors |
|
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 #include <pthread.h> |
|
18 #include <stdio.h> |
|
19 |
|
20 #include "mozilla/DebugOnly.h" |
|
21 |
|
22 #include "base/basictypes.h" |
|
23 #include "base/thread.h" |
|
24 |
|
25 #include "Hal.h" |
|
26 #include "HalSensor.h" |
|
27 #include "hardware/sensors.h" |
|
28 #include "nsThreadUtils.h" |
|
29 |
|
30 #undef LOG |
|
31 |
|
32 #include <android/log.h> |
|
33 |
|
34 using namespace mozilla::hal; |
|
35 |
|
36 #define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "GonkSensor" , ## args) |
|
37 #define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "GonkSensor" , ## args) |
|
38 |
|
39 namespace mozilla { |
|
40 |
|
41 // The value from SensorDevice.h (Android) |
|
42 #define DEFAULT_DEVICE_POLL_RATE 200000000 /*200ms*/ |
|
43 // ProcessOrientation.cpp needs smaller poll rate to detect delay between |
|
44 // different orientation angles |
|
45 #define ACCELEROMETER_POLL_RATE 66667000 /*66.667ms*/ |
|
46 |
|
47 double radToDeg(double a) { |
|
48 return a * (180.0 / M_PI); |
|
49 } |
|
50 |
|
51 static SensorType |
|
52 HardwareSensorToHalSensor(int type) |
|
53 { |
|
54 switch(type) { |
|
55 case SENSOR_TYPE_ORIENTATION: |
|
56 return SENSOR_ORIENTATION; |
|
57 case SENSOR_TYPE_ACCELEROMETER: |
|
58 return SENSOR_ACCELERATION; |
|
59 case SENSOR_TYPE_PROXIMITY: |
|
60 return SENSOR_PROXIMITY; |
|
61 case SENSOR_TYPE_LIGHT: |
|
62 return SENSOR_LIGHT; |
|
63 case SENSOR_TYPE_GYROSCOPE: |
|
64 return SENSOR_GYROSCOPE; |
|
65 case SENSOR_TYPE_LINEAR_ACCELERATION: |
|
66 return SENSOR_LINEAR_ACCELERATION; |
|
67 default: |
|
68 return SENSOR_UNKNOWN; |
|
69 } |
|
70 } |
|
71 |
|
72 static SensorAccuracyType |
|
73 HardwareStatusToHalAccuracy(int status) { |
|
74 return static_cast<SensorAccuracyType>(status); |
|
75 } |
|
76 |
|
77 static int |
|
78 HalSensorToHardwareSensor(SensorType type) |
|
79 { |
|
80 switch(type) { |
|
81 case SENSOR_ORIENTATION: |
|
82 return SENSOR_TYPE_ORIENTATION; |
|
83 case SENSOR_ACCELERATION: |
|
84 return SENSOR_TYPE_ACCELEROMETER; |
|
85 case SENSOR_PROXIMITY: |
|
86 return SENSOR_TYPE_PROXIMITY; |
|
87 case SENSOR_LIGHT: |
|
88 return SENSOR_TYPE_LIGHT; |
|
89 case SENSOR_GYROSCOPE: |
|
90 return SENSOR_TYPE_GYROSCOPE; |
|
91 case SENSOR_LINEAR_ACCELERATION: |
|
92 return SENSOR_TYPE_LINEAR_ACCELERATION; |
|
93 default: |
|
94 return -1; |
|
95 } |
|
96 } |
|
97 |
|
98 static int |
|
99 SensorseventStatus(const sensors_event_t& data) |
|
100 { |
|
101 int type = data.type; |
|
102 switch(type) { |
|
103 case SENSOR_ORIENTATION: |
|
104 return data.orientation.status; |
|
105 case SENSOR_LINEAR_ACCELERATION: |
|
106 case SENSOR_ACCELERATION: |
|
107 return data.acceleration.status; |
|
108 case SENSOR_GYROSCOPE: |
|
109 return data.gyro.status; |
|
110 } |
|
111 |
|
112 return SENSOR_STATUS_UNRELIABLE; |
|
113 } |
|
114 |
|
115 class SensorRunnable : public nsRunnable |
|
116 { |
|
117 public: |
|
118 SensorRunnable(const sensors_event_t& data, const sensor_t* sensors, ssize_t size) |
|
119 { |
|
120 mSensorData.sensor() = HardwareSensorToHalSensor(data.type); |
|
121 mSensorData.accuracy() = HardwareStatusToHalAccuracy(SensorseventStatus(data)); |
|
122 mSensorData.timestamp() = data.timestamp; |
|
123 if (mSensorData.sensor() == SENSOR_GYROSCOPE) { |
|
124 // libhardware returns gyro as rad. convert. |
|
125 mSensorValues.AppendElement(radToDeg(data.data[0])); |
|
126 mSensorValues.AppendElement(radToDeg(data.data[1])); |
|
127 mSensorValues.AppendElement(radToDeg(data.data[2])); |
|
128 } else if (mSensorData.sensor() == SENSOR_PROXIMITY) { |
|
129 mSensorValues.AppendElement(data.data[0]); |
|
130 mSensorValues.AppendElement(0); |
|
131 |
|
132 // Determine the maxRange for this sensor. |
|
133 for (ssize_t i = 0; i < size; i++) { |
|
134 if (sensors[i].type == SENSOR_TYPE_PROXIMITY) { |
|
135 mSensorValues.AppendElement(sensors[i].maxRange); |
|
136 } |
|
137 } |
|
138 } else if (mSensorData.sensor() == SENSOR_LIGHT) { |
|
139 mSensorValues.AppendElement(data.data[0]); |
|
140 } else { |
|
141 mSensorValues.AppendElement(data.data[0]); |
|
142 mSensorValues.AppendElement(data.data[1]); |
|
143 mSensorValues.AppendElement(data.data[2]); |
|
144 } |
|
145 mSensorData.values() = mSensorValues; |
|
146 } |
|
147 |
|
148 ~SensorRunnable() {} |
|
149 |
|
150 NS_IMETHOD Run() |
|
151 { |
|
152 NotifySensorChange(mSensorData); |
|
153 return NS_OK; |
|
154 } |
|
155 |
|
156 private: |
|
157 SensorData mSensorData; |
|
158 InfallibleTArray<float> mSensorValues; |
|
159 }; |
|
160 |
|
161 namespace hal_impl { |
|
162 |
|
163 static DebugOnly<int> sSensorRefCount[NUM_SENSOR_TYPE]; |
|
164 static base::Thread* sPollingThread; |
|
165 static sensors_poll_device_t* sSensorDevice; |
|
166 static sensors_module_t* sSensorModule; |
|
167 |
|
168 static void |
|
169 PollSensors() |
|
170 { |
|
171 const size_t numEventMax = 16; |
|
172 sensors_event_t buffer[numEventMax]; |
|
173 const sensor_t* sensors; |
|
174 int size = sSensorModule->get_sensors_list(sSensorModule, &sensors); |
|
175 |
|
176 do { |
|
177 // didn't check sSensorDevice because already be done on creating pollingThread. |
|
178 int n = sSensorDevice->poll(sSensorDevice, buffer, numEventMax); |
|
179 if (n < 0) { |
|
180 LOGE("Error polling for sensor data (err=%d)", n); |
|
181 break; |
|
182 } |
|
183 |
|
184 for (int i = 0; i < n; ++i) { |
|
185 // FIXME: bug 802004, add proper support for the magnetic field sensor. |
|
186 if (buffer[i].type == SENSOR_TYPE_MAGNETIC_FIELD) |
|
187 continue; |
|
188 |
|
189 // Bug 938035, transfer HAL data for orientation sensor to meet w3c spec |
|
190 // ex: HAL report alpha=90 means East but alpha=90 means West in w3c spec |
|
191 if (buffer[i].type == SENSOR_TYPE_ORIENTATION) { |
|
192 buffer[i].orientation.azimuth = 360 - buffer[i].orientation.azimuth; |
|
193 buffer[i].orientation.pitch = -buffer[i].orientation.pitch; |
|
194 buffer[i].orientation.roll = -buffer[i].orientation.roll; |
|
195 } |
|
196 |
|
197 if (HardwareSensorToHalSensor(buffer[i].type) == SENSOR_UNKNOWN) { |
|
198 // Emulator is broken and gives us events without types set |
|
199 int index; |
|
200 for (index = 0; index < size; index++) { |
|
201 if (sensors[index].handle == buffer[i].sensor) { |
|
202 break; |
|
203 } |
|
204 } |
|
205 if (index < size && |
|
206 HardwareSensorToHalSensor(sensors[index].type) != SENSOR_UNKNOWN) { |
|
207 buffer[i].type = sensors[index].type; |
|
208 } else { |
|
209 LOGW("Could not determine sensor type of event"); |
|
210 continue; |
|
211 } |
|
212 } |
|
213 |
|
214 NS_DispatchToMainThread(new SensorRunnable(buffer[i], sensors, size)); |
|
215 } |
|
216 } while (true); |
|
217 } |
|
218 |
|
219 static void |
|
220 SwitchSensor(bool aActivate, sensor_t aSensor, pthread_t aThreadId) |
|
221 { |
|
222 int index = HardwareSensorToHalSensor(aSensor.type); |
|
223 |
|
224 MOZ_ASSERT(sSensorRefCount[index] || aActivate); |
|
225 |
|
226 sSensorDevice->activate(sSensorDevice, aSensor.handle, aActivate); |
|
227 |
|
228 if (aActivate) { |
|
229 if (aSensor.type == SENSOR_TYPE_ACCELEROMETER) { |
|
230 sSensorDevice->setDelay(sSensorDevice, aSensor.handle, |
|
231 ACCELEROMETER_POLL_RATE); |
|
232 } else { |
|
233 sSensorDevice->setDelay(sSensorDevice, aSensor.handle, |
|
234 DEFAULT_DEVICE_POLL_RATE); |
|
235 } |
|
236 } |
|
237 |
|
238 if (aActivate) { |
|
239 sSensorRefCount[index]++; |
|
240 } else { |
|
241 sSensorRefCount[index]--; |
|
242 } |
|
243 } |
|
244 |
|
245 static void |
|
246 SetSensorState(SensorType aSensor, bool activate) |
|
247 { |
|
248 int type = HalSensorToHardwareSensor(aSensor); |
|
249 const sensor_t* sensors = nullptr; |
|
250 |
|
251 int size = sSensorModule->get_sensors_list(sSensorModule, &sensors); |
|
252 for (ssize_t i = 0; i < size; i++) { |
|
253 if (sensors[i].type == type) { |
|
254 SwitchSensor(activate, sensors[i], pthread_self()); |
|
255 break; |
|
256 } |
|
257 } |
|
258 } |
|
259 |
|
260 void |
|
261 EnableSensorNotifications(SensorType aSensor) |
|
262 { |
|
263 if (!sSensorModule) { |
|
264 hw_get_module(SENSORS_HARDWARE_MODULE_ID, |
|
265 (hw_module_t const**)&sSensorModule); |
|
266 if (!sSensorModule) { |
|
267 LOGE("Can't get sensor HAL module\n"); |
|
268 return; |
|
269 } |
|
270 |
|
271 sensors_open(&sSensorModule->common, &sSensorDevice); |
|
272 if (!sSensorDevice) { |
|
273 sSensorModule = nullptr; |
|
274 LOGE("Can't get sensor poll device from module \n"); |
|
275 return; |
|
276 } |
|
277 |
|
278 sensor_t const* sensors; |
|
279 int count = sSensorModule->get_sensors_list(sSensorModule, &sensors); |
|
280 for (size_t i=0 ; i<size_t(count) ; i++) { |
|
281 sSensorDevice->activate(sSensorDevice, sensors[i].handle, 0); |
|
282 } |
|
283 } |
|
284 |
|
285 if (!sPollingThread) { |
|
286 sPollingThread = new base::Thread("GonkSensors"); |
|
287 MOZ_ASSERT(sPollingThread); |
|
288 // sPollingThread never terminates because poll may never return |
|
289 sPollingThread->Start(); |
|
290 sPollingThread->message_loop()->PostTask(FROM_HERE, |
|
291 NewRunnableFunction(PollSensors)); |
|
292 } |
|
293 |
|
294 SetSensorState(aSensor, true); |
|
295 } |
|
296 |
|
297 void |
|
298 DisableSensorNotifications(SensorType aSensor) |
|
299 { |
|
300 if (!sSensorModule) { |
|
301 return; |
|
302 } |
|
303 SetSensorState(aSensor, false); |
|
304 } |
|
305 |
|
306 } // hal_impl |
|
307 } // mozilla |