Bumping manifests a=b2g-bump
[gecko.git] / hal / gonk / GonkSensor.cpp
blobb3a13ef93d56224cef838706201db9c9aa6def55
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* Copyright 2012 Mozilla Foundation and Mozilla contributors
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <pthread.h>
18 #include <stdio.h>
20 #include "mozilla/DebugOnly.h"
22 #include "base/basictypes.h"
23 #include "base/thread.h"
25 #include "Hal.h"
26 #include "HalSensor.h"
27 #include "hardware/sensors.h"
28 #include "nsThreadUtils.h"
30 #undef LOG
32 #include <android/log.h>
34 using namespace mozilla::hal;
36 #define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "GonkSensor" , ## args)
37 #define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "GonkSensor" , ## args)
39 namespace mozilla {
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*/
47 double radToDeg(double a) {
48 return a * (180.0 / M_PI);
51 static SensorType
52 HardwareSensorToHalSensor(int type)
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;
72 static SensorAccuracyType
73 HardwareStatusToHalAccuracy(int status) {
74 return static_cast<SensorAccuracyType>(status);
77 static int
78 HalSensorToHardwareSensor(SensorType type)
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;
98 static int
99 SensorseventStatus(const sensors_event_t& data)
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;
112 return SENSOR_STATUS_UNRELIABLE;
115 class SensorRunnable : public nsRunnable
117 public:
118 SensorRunnable(const sensors_event_t& data, const sensor_t* sensors, ssize_t size)
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);
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);
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]);
145 mSensorData.values() = mSensorValues;
148 ~SensorRunnable() {}
150 NS_IMETHOD Run()
152 NotifySensorChange(mSensorData);
153 return NS_OK;
156 private:
157 SensorData mSensorData;
158 InfallibleTArray<float> mSensorValues;
161 namespace hal_impl {
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;
168 static void
169 PollSensors()
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);
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;
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;
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;
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;
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;
214 NS_DispatchToMainThread(new SensorRunnable(buffer[i], sensors, size));
216 } while (true);
219 static void
220 SwitchSensor(bool aActivate, sensor_t aSensor, pthread_t aThreadId)
222 int index = HardwareSensorToHalSensor(aSensor.type);
224 MOZ_ASSERT(sSensorRefCount[index] || aActivate);
226 sSensorDevice->activate(sSensorDevice, aSensor.handle, aActivate);
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);
238 if (aActivate) {
239 sSensorRefCount[index]++;
240 } else {
241 sSensorRefCount[index]--;
245 static void
246 SetSensorState(SensorType aSensor, bool activate)
248 int type = HalSensorToHardwareSensor(aSensor);
249 const sensor_t* sensors = nullptr;
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;
260 void
261 EnableSensorNotifications(SensorType aSensor)
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;
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;
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);
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));
294 SetSensorState(aSensor, true);
297 void
298 DisableSensorNotifications(SensorType aSensor)
300 if (!sSensorModule) {
301 return;
303 SetSensorState(aSensor, false);
306 } // hal_impl
307 } // mozilla