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.
20 #include "mozilla/DebugOnly.h"
22 #include "base/basictypes.h"
23 #include "base/thread.h"
26 #include "HalSensor.h"
27 #include "hardware/sensors.h"
28 #include "nsThreadUtils.h"
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)
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
);
52 HardwareSensorToHalSensor(int 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
:
63 case SENSOR_TYPE_GYROSCOPE
:
64 return SENSOR_GYROSCOPE
;
65 case SENSOR_TYPE_LINEAR_ACCELERATION
:
66 return SENSOR_LINEAR_ACCELERATION
;
68 return SENSOR_UNKNOWN
;
72 static SensorAccuracyType
73 HardwareStatusToHalAccuracy(int status
) {
74 return static_cast<SensorAccuracyType
>(status
);
78 HalSensorToHardwareSensor(SensorType 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
;
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
;
99 SensorseventStatus(const sensors_event_t
& data
)
101 int type
= data
.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
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]);
141 mSensorValues
.AppendElement(data
.data
[0]);
142 mSensorValues
.AppendElement(data
.data
[1]);
143 mSensorValues
.AppendElement(data
.data
[2]);
145 mSensorData
.values() = mSensorValues
;
152 NotifySensorChange(mSensorData
);
157 SensorData mSensorData
;
158 InfallibleTArray
<float> mSensorValues
;
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
;
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
);
177 // didn't check sSensorDevice because already be done on creating pollingThread.
178 int n
= sSensorDevice
->poll(sSensorDevice
, buffer
, numEventMax
);
180 LOGE("Error polling for sensor data (err=%d)", n
);
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
)
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
200 for (index
= 0; index
< size
; index
++) {
201 if (sensors
[index
].handle
== buffer
[i
].sensor
) {
206 HardwareSensorToHalSensor(sensors
[index
].type
) != SENSOR_UNKNOWN
) {
207 buffer
[i
].type
= sensors
[index
].type
;
209 LOGW("Could not determine sensor type of event");
214 NS_DispatchToMainThread(new SensorRunnable(buffer
[i
], sensors
, size
));
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
);
229 if (aSensor
.type
== SENSOR_TYPE_ACCELEROMETER
) {
230 sSensorDevice
->setDelay(sSensorDevice
, aSensor
.handle
,
231 ACCELEROMETER_POLL_RATE
);
233 sSensorDevice
->setDelay(sSensorDevice
, aSensor
.handle
,
234 DEFAULT_DEVICE_POLL_RATE
);
239 sSensorRefCount
[index
]++;
241 sSensorRefCount
[index
]--;
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());
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");
271 sensors_open(&sSensorModule
->common
, &sSensorDevice
);
272 if (!sSensorDevice
) {
273 sSensorModule
= nullptr;
274 LOGE("Can't get sensor poll device from module \n");
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);
298 DisableSensorNotifications(SensorType aSensor
)
300 if (!sSensorModule
) {
303 SetSensorState(aSensor
, false);