mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 16:32:59 +00:00
275 lines
7.2 KiB
C++
275 lines
7.2 KiB
C++
/* -*- 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"
|
|
#include "nsThreadUtils.h"
|
|
|
|
#include <android/log.h>
|
|
|
|
using namespace mozilla::hal;
|
|
using namespace android;
|
|
|
|
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GonkSensor" , ## args)
|
|
|
|
namespace mozilla {
|
|
|
|
#define DEFAULT_DEVICE_POLL_RATE 100000000 /*100ms*/
|
|
|
|
double radToDeg(double a) {
|
|
return a * (180.0 / M_PI);
|
|
}
|
|
|
|
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;
|
|
case SENSOR_TYPE_LIGHT:
|
|
return SENSOR_LIGHT;
|
|
case SENSOR_TYPE_GYROSCOPE:
|
|
return SENSOR_GYROSCOPE;
|
|
case SENSOR_TYPE_LINEAR_ACCELERATION:
|
|
return SENSOR_LINEAR_ACCELERATION;
|
|
default:
|
|
return SENSOR_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
static SensorAccuracyType
|
|
HardwareStatusToHalAccuracy(int status) {
|
|
return static_cast<SensorAccuracyType>(status);
|
|
}
|
|
|
|
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;
|
|
case SENSOR_LIGHT:
|
|
return SENSOR_TYPE_LIGHT;
|
|
case SENSOR_GYROSCOPE:
|
|
return SENSOR_TYPE_GYROSCOPE;
|
|
case SENSOR_LINEAR_ACCELERATION:
|
|
return SENSOR_TYPE_LINEAR_ACCELERATION;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
static int
|
|
SensorseventStatus(const sensors_event_t& data)
|
|
{
|
|
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;
|
|
}
|
|
|
|
return SENSOR_STATUS_UNRELIABLE;
|
|
}
|
|
|
|
class SensorRunnable : public nsRunnable
|
|
{
|
|
public:
|
|
SensorRunnable(const sensors_event_t& data)
|
|
{
|
|
mSensorData.sensor() = HardwareSensorToHalSensor(data.type);
|
|
if (mSensorData.sensor() == SENSOR_UNKNOWN) {
|
|
// Emulator is broken and gives us events without types set
|
|
const sensor_t* sensors = NULL;
|
|
SensorDevice& device = SensorDevice::getInstance();
|
|
ssize_t size = device.getSensorList(&sensors);
|
|
if (data.sensor < size)
|
|
mSensorData.sensor() = HardwareSensorToHalSensor(sensors[data.sensor].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 if (mSensorData.sensor() == SENSOR_PROXIMITY) {
|
|
mSensorValues.AppendElement(data.data[0]);
|
|
mSensorValues.AppendElement(0);
|
|
|
|
// Determine the maxRange for this sensor.
|
|
const sensor_t* sensors = NULL;
|
|
ssize_t size = SensorDevice::getInstance().getSensorList(&sensors);
|
|
for (ssize_t i = 0; i < size; i++) {
|
|
if (sensors[i].type == SENSOR_TYPE_PROXIMITY) {
|
|
mSensorValues.AppendElement(sensors[i].maxRange);
|
|
}
|
|
}
|
|
} else if (mSensorData.sensor() == SENSOR_LIGHT) {
|
|
mSensorValues.AppendElement(data.data[0]);
|
|
} 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;
|
|
};
|
|
|
|
namespace hal_impl {
|
|
|
|
class SensorStatus {
|
|
public:
|
|
SensorData data;
|
|
DebugOnly<int> count;
|
|
};
|
|
|
|
static int sActivatedSensors = 0;
|
|
static SensorStatus sSensorStatus[NUM_SENSOR_TYPE];
|
|
static nsCOMPtr<nsIThread> sSwitchThread;
|
|
|
|
class PollSensor {
|
|
public:
|
|
NS_INLINE_DECL_REFCOUNTING(PollSensor);
|
|
|
|
static nsCOMPtr<nsIRunnable> GetRunnable() {
|
|
if (!mRunnable)
|
|
mRunnable = NS_NewRunnableMethod(new PollSensor(), &PollSensor::Poll);
|
|
return mRunnable;
|
|
}
|
|
|
|
void Poll() {
|
|
if (!sActivatedSensors) {
|
|
return;
|
|
}
|
|
|
|
SensorDevice &device = SensorDevice::getInstance();
|
|
const size_t numEventMax = 16;
|
|
sensors_event_t buffer[numEventMax];
|
|
|
|
int n = device.poll(buffer, numEventMax);
|
|
if (n < 0) {
|
|
LOG("Error polling for sensor data (err=%d)", n);
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
NS_DispatchToMainThread(new SensorRunnable(buffer[i]));
|
|
}
|
|
|
|
if (sActivatedSensors) {
|
|
sSwitchThread->Dispatch(GetRunnable(), NS_DISPATCH_NORMAL);
|
|
}
|
|
}
|
|
private:
|
|
static nsCOMPtr<nsIRunnable> mRunnable;
|
|
};
|
|
|
|
nsCOMPtr<nsIRunnable> PollSensor::mRunnable = NULL;
|
|
|
|
class SwitchSensor {
|
|
public:
|
|
NS_INLINE_DECL_REFCOUNTING(SwitchSensor)
|
|
|
|
SwitchSensor(bool aActivate, sensor_t aSensor, pthread_t aThreadId) :
|
|
mActivate(aActivate), mSensor(aSensor), mThreadId(aThreadId) { }
|
|
|
|
void Switch() {
|
|
int index = HardwareSensorToHalSensor(mSensor.type);
|
|
|
|
MOZ_ASSERT(sSensorStatus[index].count == 0 || mActivate);
|
|
|
|
SensorDevice& device = SensorDevice::getInstance();
|
|
|
|
device.activate((void*)mThreadId, mSensor.handle, mActivate);
|
|
device.setDelay((void*)mThreadId, mSensor.handle, DEFAULT_DEVICE_POLL_RATE);
|
|
|
|
if (mActivate) {
|
|
if (++sActivatedSensors == 1) {
|
|
sSwitchThread->Dispatch(PollSensor::GetRunnable(), NS_DISPATCH_NORMAL);
|
|
}
|
|
sSensorStatus[index].count++;
|
|
} else {
|
|
sSensorStatus[index].count--;
|
|
--sActivatedSensors;
|
|
}
|
|
}
|
|
|
|
protected:
|
|
SwitchSensor() { };
|
|
bool mActivate;
|
|
sensor_t mSensor;
|
|
pthread_t mThreadId;
|
|
};
|
|
|
|
|
|
static void
|
|
SetSensorState(SensorType aSensor, bool activate)
|
|
{
|
|
int type = HalSensorToHardwareSensor(aSensor);
|
|
const sensor_t* sensors = NULL;
|
|
SensorDevice& device = SensorDevice::getInstance();
|
|
ssize_t size = device.getSensorList(&sensors);
|
|
for (ssize_t i = 0; i < size; i++) {
|
|
if (sensors[i].type == type) {
|
|
// Post an event to the sensor thread
|
|
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(new SwitchSensor(activate, sensors[i], pthread_self()),
|
|
&SwitchSensor::Switch);
|
|
|
|
sSwitchThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
EnableSensorNotifications(SensorType aSensor)
|
|
{
|
|
if (sSwitchThread == nsnull) {
|
|
NS_NewThread(getter_AddRefs(sSwitchThread));
|
|
}
|
|
|
|
SetSensorState(aSensor, true);
|
|
}
|
|
|
|
void
|
|
DisableSensorNotifications(SensorType aSensor)
|
|
{
|
|
SetSensorState(aSensor, false);
|
|
}
|
|
|
|
} // hal_impl
|
|
} // mozilla
|