2012-02-06 06:41:15 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "Hal.h"
|
|
|
|
#include "HalSensor.h"
|
|
|
|
#include "hardware/sensors.h"
|
|
|
|
#include "mozilla/Util.h"
|
|
|
|
#include "SensorDevice.h"
|
2012-03-07 20:27:09 +04:00
|
|
|
#include "nsThreadUtils.h"
|
2012-02-06 06:41:15 +04:00
|
|
|
|
|
|
|
using namespace mozilla::hal;
|
|
|
|
using namespace android;
|
|
|
|
|
2012-03-07 20:27:09 +04:00
|
|
|
namespace mozilla {
|
|
|
|
|
2012-03-21 10:36:17 +04:00
|
|
|
#define DEFAULT_DEVICE_POLL_RATE 100000000 /*100ms*/
|
|
|
|
|
|
|
|
|
|
|
|
double radToDeg(double a) {
|
|
|
|
return a * (180.0 / M_PI);
|
|
|
|
}
|
|
|
|
|
2012-02-06 06:41:15 +04:00
|
|
|
static SensorType
|
|
|
|
HardwareSensorToHalSensor(int type)
|
|
|
|
{
|
|
|
|
switch(type) {
|
|
|
|
case SENSOR_TYPE_ORIENTATION:
|
|
|
|
return SENSOR_ORIENTATION;
|
|
|
|
case SENSOR_TYPE_ACCELEROMETER:
|
|
|
|
return SENSOR_ACCELERATION;
|
|
|
|
case SENSOR_TYPE_PROXIMITY:
|
|
|
|
return SENSOR_PROXIMITY;
|
2012-03-21 10:36:17 +04:00
|
|
|
case SENSOR_TYPE_GYROSCOPE:
|
|
|
|
return SENSOR_GYROSCOPE;
|
|
|
|
case SENSOR_TYPE_LINEAR_ACCELERATION:
|
|
|
|
return SENSOR_LINEAR_ACCELERATION;
|
2012-02-06 06:41:15 +04:00
|
|
|
default:
|
|
|
|
return SENSOR_UNKNOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-21 10:36:17 +04:00
|
|
|
static SensorAccuracyType
|
|
|
|
HardwareStatusToHalAccuracy(int status) {
|
|
|
|
return static_cast<SensorAccuracyType>(status);
|
|
|
|
}
|
|
|
|
|
2012-02-06 06:41:15 +04:00
|
|
|
static int
|
|
|
|
HalSensorToHardwareSensor(SensorType type)
|
|
|
|
{
|
|
|
|
switch(type) {
|
|
|
|
case SENSOR_ORIENTATION:
|
|
|
|
return SENSOR_TYPE_ORIENTATION;
|
|
|
|
case SENSOR_ACCELERATION:
|
|
|
|
return SENSOR_TYPE_ACCELEROMETER;
|
|
|
|
case SENSOR_PROXIMITY:
|
|
|
|
return SENSOR_TYPE_PROXIMITY;
|
2012-03-21 10:36:17 +04:00
|
|
|
case SENSOR_GYROSCOPE:
|
|
|
|
return SENSOR_TYPE_GYROSCOPE;
|
|
|
|
case SENSOR_LINEAR_ACCELERATION:
|
|
|
|
return SENSOR_TYPE_LINEAR_ACCELERATION;
|
2012-02-06 06:41:15 +04:00
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-21 10:36:17 +04:00
|
|
|
static int
|
|
|
|
SensorseventStatus(const sensors_event_t& data)
|
2012-02-06 06:41:15 +04:00
|
|
|
{
|
2012-03-21 10:36:17 +04:00
|
|
|
int type = data.type;
|
|
|
|
switch(type) {
|
|
|
|
case SENSOR_ORIENTATION:
|
|
|
|
return data.orientation.status;
|
|
|
|
case SENSOR_LINEAR_ACCELERATION:
|
|
|
|
case SENSOR_ACCELERATION:
|
|
|
|
return data.acceleration.status;
|
|
|
|
case SENSOR_GYROSCOPE:
|
|
|
|
return data.gyro.status;
|
|
|
|
}
|
2012-02-06 06:41:15 +04:00
|
|
|
|
|
|
|
|
2012-03-21 10:36:17 +04:00
|
|
|
return SENSOR_STATUS_UNRELIABLE;
|
2012-02-06 06:41:15 +04:00
|
|
|
}
|
|
|
|
|
2012-03-21 10:36:17 +04:00
|
|
|
class SensorRunnable : public nsRunnable
|
2012-02-06 06:41:15 +04:00
|
|
|
{
|
2012-03-21 10:36:17 +04:00
|
|
|
public:
|
|
|
|
SensorRunnable(const sensors_event_t& data)
|
|
|
|
{
|
|
|
|
mSensorData.sensor() = HardwareSensorToHalSensor(data.type);
|
|
|
|
mSensorData.accuracy() = HardwareStatusToHalAccuracy(SensorseventStatus(data));
|
|
|
|
mSensorData.timestamp() = data.timestamp;
|
|
|
|
if (mSensorData.sensor() == SENSOR_GYROSCOPE) {
|
|
|
|
// libhardware returns gyro as rad. convert.
|
|
|
|
mSensorValues.AppendElement(radToDeg(data.data[0]));
|
|
|
|
mSensorValues.AppendElement(radToDeg(data.data[1]));
|
|
|
|
mSensorValues.AppendElement(radToDeg(data.data[2]));
|
|
|
|
} else {
|
|
|
|
mSensorValues.AppendElement(data.data[0]);
|
|
|
|
mSensorValues.AppendElement(data.data[1]);
|
|
|
|
mSensorValues.AppendElement(data.data[2]);
|
|
|
|
}
|
|
|
|
mSensorData.values() = mSensorValues;
|
|
|
|
}
|
|
|
|
|
|
|
|
~SensorRunnable() {}
|
|
|
|
|
|
|
|
NS_IMETHOD Run()
|
|
|
|
{
|
|
|
|
NotifySensorChange(mSensorData);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
SensorData mSensorData;
|
|
|
|
InfallibleTArray<float> mSensorValues;
|
|
|
|
};
|
2012-02-06 06:41:15 +04:00
|
|
|
|
|
|
|
namespace hal_impl {
|
|
|
|
|
|
|
|
static pthread_t sThread;
|
2012-03-21 10:36:17 +04:00
|
|
|
static bool sInitialized = false;
|
|
|
|
static bool sContinue = true;
|
|
|
|
static int sActivatedSensors = 0;
|
2012-03-07 20:27:09 +04:00
|
|
|
static nsCOMPtr<nsIThread> sSwitchThread;
|
2012-02-06 06:41:15 +04:00
|
|
|
|
|
|
|
static void*
|
|
|
|
UpdateSensorData(void* /*unused*/)
|
|
|
|
{
|
|
|
|
SensorDevice &device = SensorDevice::getInstance();
|
|
|
|
const size_t numEventMax = 16;
|
|
|
|
sensors_event_t buffer[numEventMax];
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
while (sContinue) {
|
|
|
|
count = device.poll(buffer, numEventMax);
|
2012-03-21 10:36:17 +04:00
|
|
|
|
2012-02-06 06:41:15 +04:00
|
|
|
if (count < 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i=0; i<count; i++) {
|
2012-03-21 10:36:17 +04:00
|
|
|
if (SensorseventStatus(buffer[i]) == SENSOR_STATUS_UNRELIABLE) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
NS_DispatchToMainThread(new SensorRunnable(buffer[i]));
|
2012-02-06 06:41:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-07 20:27:09 +04:00
|
|
|
InitializeResources()
|
2012-02-06 06:41:15 +04:00
|
|
|
{
|
2012-03-21 03:59:24 +04:00
|
|
|
sInitialized = true;
|
|
|
|
sContinue = true;
|
2012-03-21 10:36:17 +04:00
|
|
|
pthread_create(&sThread, NULL, &UpdateSensorData, NULL);
|
|
|
|
NS_NewThread(getter_AddRefs(sSwitchThread));
|
2012-02-06 06:41:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ReleaseResources()
|
|
|
|
{
|
|
|
|
sContinue = false;
|
|
|
|
pthread_join(sThread, NULL);
|
2012-03-07 20:27:09 +04:00
|
|
|
sSwitchThread->Shutdown();
|
2012-02-06 06:41:15 +04:00
|
|
|
sInitialized = false;
|
|
|
|
}
|
|
|
|
|
2012-03-07 20:27:09 +04:00
|
|
|
// This class is used as a runnable on the sSwitchThread
|
|
|
|
class SensorInfo {
|
|
|
|
public:
|
|
|
|
NS_INLINE_DECL_REFCOUNTING(SensorInfo)
|
|
|
|
|
|
|
|
SensorInfo(bool aActivate, sensor_t aSensor, pthread_t aThreadId) :
|
|
|
|
activate(aActivate), sensor(aSensor), threadId(aThreadId) { }
|
|
|
|
|
|
|
|
void Switch() {
|
|
|
|
SensorDevice& device = SensorDevice::getInstance();
|
|
|
|
device.activate((void*)threadId, sensor.handle, activate);
|
2012-03-21 10:36:17 +04:00
|
|
|
device.setDelay((void*)threadId, sensor.handle, DEFAULT_DEVICE_POLL_RATE);
|
2012-03-07 20:27:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
SensorInfo() { };
|
|
|
|
bool activate;
|
|
|
|
sensor_t sensor;
|
|
|
|
pthread_t threadId;
|
|
|
|
};
|
|
|
|
|
2012-02-06 06:41:15 +04:00
|
|
|
static void
|
|
|
|
SensorSwitch(SensorType aSensor, bool activate)
|
|
|
|
{
|
|
|
|
int type = HalSensorToHardwareSensor(aSensor);
|
|
|
|
const sensor_t* sensors = NULL;
|
|
|
|
SensorDevice& device = SensorDevice::getInstance();
|
|
|
|
size_t size = device.getSensorList(&sensors);
|
2012-03-07 20:27:09 +04:00
|
|
|
for (size_t i = 0; i < size; i++) {
|
2012-02-06 06:41:15 +04:00
|
|
|
if (sensors[i].type == type) {
|
2012-03-07 20:27:09 +04:00
|
|
|
// Post an event to the activation thread
|
|
|
|
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(new SensorInfo(activate, sensors[i], pthread_self()),
|
|
|
|
&SensorInfo::Switch);
|
|
|
|
sSwitchThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
2012-02-06 06:41:15 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
EnableSensorNotifications(SensorType aSensor)
|
|
|
|
{
|
|
|
|
if (!sInitialized) {
|
2012-03-07 20:27:09 +04:00
|
|
|
InitializeResources();
|
2012-02-06 06:41:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
SensorSwitch(aSensor, true);
|
|
|
|
sActivatedSensors++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
DisableSensorNotifications(SensorType aSensor)
|
|
|
|
{
|
|
|
|
if (!sInitialized) {
|
|
|
|
NS_WARNING("Disable sensors without initializing first");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SensorSwitch(aSensor, false);
|
|
|
|
sActivatedSensors--;
|
|
|
|
|
|
|
|
if (!sActivatedSensors) {
|
|
|
|
ReleaseResources();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // hal_impl
|
|
|
|
} // mozilla
|