2012-02-06 06:41:15 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2012-07-20 13:10:44 +04:00
|
|
|
/* Copyright 2012 Mozilla Foundation and Mozilla contributors
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
2012-02-06 06:41:15 +04:00
|
|
|
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2012-12-15 03:58:45 +04:00
|
|
|
#include "mozilla/DebugOnly.h"
|
2016-02-04 14:35:13 +03:00
|
|
|
#include "mozilla/Saturate.h"
|
2012-12-15 03:58:45 +04:00
|
|
|
|
2012-08-29 19:26:18 +04:00
|
|
|
#include "base/basictypes.h"
|
|
|
|
#include "base/thread.h"
|
2016-05-18 19:25:35 +03:00
|
|
|
#include "base/task.h"
|
2012-08-29 19:26:18 +04:00
|
|
|
|
2016-02-04 14:35:13 +03:00
|
|
|
#include "GonkSensorsInterface.h"
|
|
|
|
#include "GonkSensorsPollInterface.h"
|
|
|
|
#include "GonkSensorsRegistryInterface.h"
|
2012-02-06 06:41:15 +04:00
|
|
|
#include "Hal.h"
|
2014-09-24 17:23:18 +04:00
|
|
|
#include "HalLog.h"
|
2012-02-06 06:41:15 +04:00
|
|
|
#include "HalSensor.h"
|
|
|
|
#include "hardware/sensors.h"
|
2013-08-28 08:14:57 +04:00
|
|
|
#include "nsThreadUtils.h"
|
2012-09-18 06:51:35 +04:00
|
|
|
|
2012-08-29 19:26:18 +04:00
|
|
|
using namespace mozilla::hal;
|
2012-02-06 06:41:15 +04:00
|
|
|
|
2012-03-07 20:27:09 +04:00
|
|
|
namespace mozilla {
|
|
|
|
|
2016-02-04 14:35:13 +03:00
|
|
|
//
|
|
|
|
// Internal implementation
|
|
|
|
//
|
|
|
|
|
2012-09-18 06:51:35 +04:00
|
|
|
// The value from SensorDevice.h (Android)
|
|
|
|
#define DEFAULT_DEVICE_POLL_RATE 200000000 /*200ms*/
|
2013-08-28 07:10:57 +04:00
|
|
|
// ProcessOrientation.cpp needs smaller poll rate to detect delay between
|
|
|
|
// different orientation angles
|
|
|
|
#define ACCELEROMETER_POLL_RATE 66667000 /*66.667ms*/
|
2012-03-21 10:36:17 +04:00
|
|
|
|
2015-04-01 23:02:20 +03:00
|
|
|
// This is present in Android from API level 18 onwards, which is 4.3. We might
|
|
|
|
// be building on something before 4.3, so use a local define for its value
|
|
|
|
#define MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR 15
|
|
|
|
|
2012-03-21 10:36:17 +04:00
|
|
|
double radToDeg(double a) {
|
|
|
|
return a * (180.0 / M_PI);
|
|
|
|
}
|
|
|
|
|
2012-02-06 06:41:15 +04:00
|
|
|
static SensorType
|
|
|
|
HardwareSensorToHalSensor(int type)
|
2012-09-18 06:51:35 +04:00
|
|
|
{
|
2012-02-06 06:41:15 +04:00
|
|
|
switch(type) {
|
|
|
|
case SENSOR_TYPE_ORIENTATION:
|
|
|
|
return SENSOR_ORIENTATION;
|
|
|
|
case SENSOR_TYPE_ACCELEROMETER:
|
|
|
|
return SENSOR_ACCELERATION;
|
|
|
|
case SENSOR_TYPE_PROXIMITY:
|
|
|
|
return SENSOR_PROXIMITY;
|
2012-05-02 20:43:45 +04:00
|
|
|
case SENSOR_TYPE_LIGHT:
|
|
|
|
return SENSOR_LIGHT;
|
2012-03-21 10:36:17 +04:00
|
|
|
case SENSOR_TYPE_GYROSCOPE:
|
|
|
|
return SENSOR_GYROSCOPE;
|
|
|
|
case SENSOR_TYPE_LINEAR_ACCELERATION:
|
|
|
|
return SENSOR_LINEAR_ACCELERATION;
|
2015-04-01 23:02:20 +03:00
|
|
|
case SENSOR_TYPE_ROTATION_VECTOR:
|
|
|
|
return SENSOR_ROTATION_VECTOR;
|
|
|
|
case MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR:
|
|
|
|
return SENSOR_GAME_ROTATION_VECTOR;
|
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-05-02 20:43:45 +04:00
|
|
|
case SENSOR_LIGHT:
|
|
|
|
return SENSOR_TYPE_LIGHT;
|
2012-03-21 10:36:17 +04:00
|
|
|
case SENSOR_GYROSCOPE:
|
|
|
|
return SENSOR_TYPE_GYROSCOPE;
|
|
|
|
case SENSOR_LINEAR_ACCELERATION:
|
|
|
|
return SENSOR_TYPE_LINEAR_ACCELERATION;
|
2015-04-01 23:02:20 +03:00
|
|
|
case SENSOR_ROTATION_VECTOR:
|
|
|
|
return SENSOR_TYPE_ROTATION_VECTOR;
|
|
|
|
case SENSOR_GAME_ROTATION_VECTOR:
|
|
|
|
return MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR;
|
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
|
|
|
}
|
|
|
|
|
2016-04-27 13:05:40 +03:00
|
|
|
class SensorRunnable : public Runnable
|
2012-02-06 06:41:15 +04:00
|
|
|
{
|
2012-03-21 10:36:17 +04:00
|
|
|
public:
|
2012-09-18 06:51:35 +04:00
|
|
|
SensorRunnable(const sensors_event_t& data, const sensor_t* sensors, ssize_t size)
|
2012-03-21 10:36:17 +04:00
|
|
|
{
|
|
|
|
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]));
|
2012-05-02 20:43:45 +04:00
|
|
|
} else if (mSensorData.sensor() == SENSOR_PROXIMITY) {
|
|
|
|
mSensorValues.AppendElement(data.data[0]);
|
2012-09-18 06:51:35 +04:00
|
|
|
mSensorValues.AppendElement(0);
|
2012-05-02 20:43:45 +04:00
|
|
|
|
|
|
|
// Determine the maxRange for this sensor.
|
2012-05-16 22:52:00 +04:00
|
|
|
for (ssize_t i = 0; i < size; i++) {
|
2012-05-02 20:43:45 +04:00
|
|
|
if (sensors[i].type == SENSOR_TYPE_PROXIMITY) {
|
2012-09-18 06:51:35 +04:00
|
|
|
mSensorValues.AppendElement(sensors[i].maxRange);
|
2012-05-02 20:43:45 +04:00
|
|
|
}
|
|
|
|
}
|
2012-05-02 20:43:45 +04:00
|
|
|
} else if (mSensorData.sensor() == SENSOR_LIGHT) {
|
|
|
|
mSensorValues.AppendElement(data.data[0]);
|
2015-04-01 23:02:20 +03:00
|
|
|
} else if (mSensorData.sensor() == SENSOR_ROTATION_VECTOR) {
|
|
|
|
mSensorValues.AppendElement(data.data[0]);
|
|
|
|
mSensorValues.AppendElement(data.data[1]);
|
|
|
|
mSensorValues.AppendElement(data.data[2]);
|
|
|
|
if (data.data[3] == 0.0) {
|
|
|
|
// data.data[3] was optional in Android <= API level 18. It can be computed from 012,
|
|
|
|
// but it's better to take the actual value if one is provided. The computation is
|
|
|
|
// v = 1 - d[0]*d[0] - d[1]*d[1] - d[2]*d[2]
|
|
|
|
// d[3] = v > 0 ? sqrt(v) : 0;
|
|
|
|
// I'm assuming that it will be 0 if it's not passed in. (The values form a unit
|
|
|
|
// quaternion, so the angle can be computed from the direction vector.)
|
|
|
|
float sx = data.data[0], sy = data.data[1], sz = data.data[2];
|
|
|
|
float v = 1.0f - sx*sx - sy*sy - sz*sz;
|
|
|
|
mSensorValues.AppendElement(v > 0.0f ? sqrt(v) : 0.0f);
|
|
|
|
} else {
|
|
|
|
mSensorValues.AppendElement(data.data[3]);
|
|
|
|
}
|
|
|
|
} else if (mSensorData.sensor() == SENSOR_GAME_ROTATION_VECTOR) {
|
|
|
|
mSensorValues.AppendElement(data.data[0]);
|
|
|
|
mSensorValues.AppendElement(data.data[1]);
|
|
|
|
mSensorValues.AppendElement(data.data[2]);
|
|
|
|
mSensorValues.AppendElement(data.data[3]);
|
2012-03-21 10:36:17 +04:00
|
|
|
} else {
|
|
|
|
mSensorValues.AppendElement(data.data[0]);
|
|
|
|
mSensorValues.AppendElement(data.data[1]);
|
|
|
|
mSensorValues.AppendElement(data.data[2]);
|
|
|
|
}
|
|
|
|
mSensorData.values() = mSensorValues;
|
|
|
|
}
|
|
|
|
|
|
|
|
~SensorRunnable() {}
|
|
|
|
|
2016-08-08 05:18:10 +03:00
|
|
|
NS_IMETHOD Run() override
|
2012-03-21 10:36:17 +04:00
|
|
|
{
|
|
|
|
NotifySensorChange(mSensorData);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
SensorData mSensorData;
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<float, 4> mSensorValues;
|
2012-03-21 10:36:17 +04:00
|
|
|
};
|
2012-02-06 06:41:15 +04:00
|
|
|
|
|
|
|
namespace hal_impl {
|
|
|
|
|
2012-09-04 13:56:20 +04:00
|
|
|
static DebugOnly<int> sSensorRefCount[NUM_SENSOR_TYPE];
|
2012-09-18 06:51:35 +04:00
|
|
|
static base::Thread* sPollingThread;
|
|
|
|
static sensors_poll_device_t* sSensorDevice;
|
|
|
|
static sensors_module_t* sSensorModule;
|
2012-03-26 11:59:02 +04:00
|
|
|
|
2012-08-29 19:26:18 +04:00
|
|
|
static void
|
2012-09-18 06:51:35 +04:00
|
|
|
PollSensors()
|
2012-08-29 19:26:18 +04:00
|
|
|
{
|
|
|
|
const size_t numEventMax = 16;
|
|
|
|
sensors_event_t buffer[numEventMax];
|
2012-09-18 06:51:35 +04:00
|
|
|
const sensor_t* sensors;
|
|
|
|
int size = sSensorModule->get_sensors_list(sSensorModule, &sensors);
|
|
|
|
|
|
|
|
do {
|
|
|
|
// didn't check sSensorDevice because already be done on creating pollingThread.
|
|
|
|
int n = sSensorDevice->poll(sSensorDevice, buffer, numEventMax);
|
|
|
|
if (n < 0) {
|
2014-09-24 17:23:18 +04:00
|
|
|
HAL_ERR("Error polling for sensor data (err=%d)", n);
|
2012-09-18 06:51:35 +04:00
|
|
|
break;
|
|
|
|
}
|
2012-02-06 06:41:15 +04:00
|
|
|
|
2012-09-18 06:51:35 +04:00
|
|
|
for (int i = 0; i < n; ++i) {
|
2012-10-16 09:11:06 +04:00
|
|
|
// FIXME: bug 802004, add proper support for the magnetic field sensor.
|
|
|
|
if (buffer[i].type == SENSOR_TYPE_MAGNETIC_FIELD)
|
|
|
|
continue;
|
|
|
|
|
2013-11-26 22:58:15 +04:00
|
|
|
// Bug 938035, transfer HAL data for orientation sensor to meet w3c spec
|
|
|
|
// ex: HAL report alpha=90 means East but alpha=90 means West in w3c spec
|
|
|
|
if (buffer[i].type == SENSOR_TYPE_ORIENTATION) {
|
|
|
|
buffer[i].orientation.azimuth = 360 - buffer[i].orientation.azimuth;
|
|
|
|
buffer[i].orientation.pitch = -buffer[i].orientation.pitch;
|
|
|
|
buffer[i].orientation.roll = -buffer[i].orientation.roll;
|
|
|
|
}
|
|
|
|
|
2012-10-31 11:03:19 +04:00
|
|
|
if (HardwareSensorToHalSensor(buffer[i].type) == SENSOR_UNKNOWN) {
|
|
|
|
// Emulator is broken and gives us events without types set
|
2013-01-24 06:45:07 +04:00
|
|
|
int index;
|
|
|
|
for (index = 0; index < size; index++) {
|
|
|
|
if (sensors[index].handle == buffer[i].sensor) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (index < size &&
|
|
|
|
HardwareSensorToHalSensor(sensors[index].type) != SENSOR_UNKNOWN) {
|
|
|
|
buffer[i].type = sensors[index].type;
|
2012-10-31 11:03:19 +04:00
|
|
|
} else {
|
2014-09-24 17:23:18 +04:00
|
|
|
HAL_LOG("Could not determine sensor type of event");
|
2012-10-31 11:03:19 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-18 06:51:35 +04:00
|
|
|
NS_DispatchToMainThread(new SensorRunnable(buffer[i], sensors, size));
|
|
|
|
}
|
|
|
|
} while (true);
|
2012-08-29 19:26:18 +04:00
|
|
|
}
|
2012-02-06 06:41:15 +04:00
|
|
|
|
2012-08-29 19:26:18 +04:00
|
|
|
static void
|
|
|
|
SwitchSensor(bool aActivate, sensor_t aSensor, pthread_t aThreadId)
|
|
|
|
{
|
|
|
|
int index = HardwareSensorToHalSensor(aSensor.type);
|
2012-03-07 20:27:09 +04:00
|
|
|
|
2012-09-04 13:56:20 +04:00
|
|
|
MOZ_ASSERT(sSensorRefCount[index] || aActivate);
|
2012-03-26 11:59:02 +04:00
|
|
|
|
2012-09-18 06:51:35 +04:00
|
|
|
sSensorDevice->activate(sSensorDevice, aSensor.handle, aActivate);
|
2012-03-26 11:59:02 +04:00
|
|
|
|
2012-09-18 06:51:35 +04:00
|
|
|
if (aActivate) {
|
2013-08-28 07:10:57 +04:00
|
|
|
if (aSensor.type == SENSOR_TYPE_ACCELEROMETER) {
|
|
|
|
sSensorDevice->setDelay(sSensorDevice, aSensor.handle,
|
|
|
|
ACCELEROMETER_POLL_RATE);
|
|
|
|
} else {
|
|
|
|
sSensorDevice->setDelay(sSensorDevice, aSensor.handle,
|
2012-09-18 06:51:35 +04:00
|
|
|
DEFAULT_DEVICE_POLL_RATE);
|
2013-08-28 07:10:57 +04:00
|
|
|
}
|
2012-09-18 06:51:35 +04:00
|
|
|
}
|
2012-03-26 11:59:02 +04:00
|
|
|
|
2012-08-29 19:26:18 +04:00
|
|
|
if (aActivate) {
|
2012-09-04 13:56:20 +04:00
|
|
|
sSensorRefCount[index]++;
|
2012-08-29 19:26:18 +04:00
|
|
|
} else {
|
2012-09-04 13:56:20 +04:00
|
|
|
sSensorRefCount[index]--;
|
2012-08-29 19:26:18 +04:00
|
|
|
}
|
|
|
|
}
|
2012-03-26 11:59:02 +04:00
|
|
|
|
2012-02-06 06:41:15 +04:00
|
|
|
static void
|
2012-03-26 11:59:02 +04:00
|
|
|
SetSensorState(SensorType aSensor, bool activate)
|
2012-02-06 06:41:15 +04:00
|
|
|
{
|
|
|
|
int type = HalSensorToHardwareSensor(aSensor);
|
2013-08-23 23:51:15 +04:00
|
|
|
const sensor_t* sensors = nullptr;
|
2012-09-18 06:51:35 +04:00
|
|
|
|
|
|
|
int size = sSensorModule->get_sensors_list(sSensorModule, &sensors);
|
2012-05-16 22:52:00 +04:00
|
|
|
for (ssize_t i = 0; i < size; i++) {
|
2012-02-06 06:41:15 +04:00
|
|
|
if (sensors[i].type == type) {
|
2012-09-18 06:51:35 +04:00
|
|
|
SwitchSensor(activate, sensors[i], pthread_self());
|
2012-02-06 06:41:15 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-04 14:35:13 +03:00
|
|
|
static void
|
|
|
|
EnableSensorNotificationsInternal(SensorType aSensor)
|
2012-02-06 06:41:15 +04:00
|
|
|
{
|
2012-09-18 06:51:35 +04:00
|
|
|
if (!sSensorModule) {
|
|
|
|
hw_get_module(SENSORS_HARDWARE_MODULE_ID,
|
|
|
|
(hw_module_t const**)&sSensorModule);
|
|
|
|
if (!sSensorModule) {
|
2014-09-24 17:23:18 +04:00
|
|
|
HAL_ERR("Can't get sensor HAL module\n");
|
2012-09-18 06:51:35 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sensors_open(&sSensorModule->common, &sSensorDevice);
|
|
|
|
if (!sSensorDevice) {
|
2013-08-23 23:51:15 +04:00
|
|
|
sSensorModule = nullptr;
|
2014-09-24 17:23:18 +04:00
|
|
|
HAL_ERR("Can't get sensor poll device from module \n");
|
2012-09-18 06:51:35 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sensor_t const* sensors;
|
|
|
|
int count = sSensorModule->get_sensors_list(sSensorModule, &sensors);
|
|
|
|
for (size_t i=0 ; i<size_t(count) ; i++) {
|
|
|
|
sSensorDevice->activate(sSensorDevice, sensors[i].handle, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sPollingThread) {
|
|
|
|
sPollingThread = new base::Thread("GonkSensors");
|
|
|
|
MOZ_ASSERT(sPollingThread);
|
|
|
|
// sPollingThread never terminates because poll may never return
|
|
|
|
sPollingThread->Start();
|
2016-05-02 20:27:15 +03:00
|
|
|
sPollingThread->message_loop()->PostTask(
|
|
|
|
NewRunnableFunction(PollSensors));
|
2012-02-06 06:41:15 +04:00
|
|
|
}
|
2012-09-18 06:51:35 +04:00
|
|
|
|
2012-03-26 11:59:02 +04:00
|
|
|
SetSensorState(aSensor, true);
|
2012-02-06 06:41:15 +04:00
|
|
|
}
|
|
|
|
|
2016-02-04 14:35:13 +03:00
|
|
|
static void
|
|
|
|
DisableSensorNotificationsInternal(SensorType aSensor)
|
2012-02-06 06:41:15 +04:00
|
|
|
{
|
2012-09-18 06:51:35 +04:00
|
|
|
if (!sSensorModule) {
|
|
|
|
return;
|
|
|
|
}
|
2012-03-26 11:59:02 +04:00
|
|
|
SetSensorState(aSensor, false);
|
2012-02-06 06:41:15 +04:00
|
|
|
}
|
|
|
|
|
2016-02-04 14:35:13 +03:00
|
|
|
//
|
|
|
|
// Daemon
|
|
|
|
//
|
|
|
|
|
|
|
|
typedef detail::SaturateOp<uint32_t> SaturateOpUint32;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The poll notification handler receives all events about sensors and
|
|
|
|
* sensor events.
|
|
|
|
*/
|
|
|
|
class SensorsPollNotificationHandler final
|
|
|
|
: public GonkSensorsPollNotificationHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SensorsPollNotificationHandler(GonkSensorsPollInterface* aPollInterface)
|
|
|
|
: mPollInterface(aPollInterface)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mPollInterface);
|
|
|
|
|
|
|
|
mPollInterface->SetNotificationHandler(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EnableSensorsByType(SensorsType aType)
|
|
|
|
{
|
|
|
|
if (SaturateOpUint32(mClasses[aType].mActivated)++) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SensorsDeliveryMode deliveryMode = DefaultSensorsDeliveryMode(aType);
|
|
|
|
|
|
|
|
// Old ref-count for the sensor type was 0, so we
|
|
|
|
// activate all sensors of the type.
|
|
|
|
for (size_t i = 0; i < mSensors.Length(); ++i) {
|
|
|
|
if (mSensors[i].mType == aType &&
|
|
|
|
mSensors[i].mDeliveryMode == deliveryMode) {
|
|
|
|
mPollInterface->EnableSensor(mSensors[i].mId, nullptr);
|
|
|
|
mPollInterface->SetPeriod(mSensors[i].mId, DefaultSensorPeriod(aType),
|
|
|
|
nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisableSensorsByType(SensorsType aType)
|
|
|
|
{
|
|
|
|
if (SaturateOpUint32(mClasses[aType].mActivated)-- != 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SensorsDeliveryMode deliveryMode = DefaultSensorsDeliveryMode(aType);
|
|
|
|
|
|
|
|
// Old ref-count for the sensor type was 1, so we
|
|
|
|
// deactivate all sensors of the type.
|
|
|
|
for (size_t i = 0; i < mSensors.Length(); ++i) {
|
|
|
|
if (mSensors[i].mType == aType &&
|
|
|
|
mSensors[i].mDeliveryMode == deliveryMode) {
|
|
|
|
mPollInterface->DisableSensor(mSensors[i].mId, nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearSensorClasses()
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(mClasses); ++i) {
|
|
|
|
mClasses[i] = SensorsSensorClass();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearSensors()
|
|
|
|
{
|
|
|
|
mSensors.Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Methods for SensorsPollNotificationHandler
|
|
|
|
//
|
|
|
|
|
|
|
|
void ErrorNotification(SensorsError aError) override
|
|
|
|
{
|
|
|
|
// XXX: Bug 1206056: Try to repair some of the errors or restart cleanly.
|
|
|
|
}
|
|
|
|
|
|
|
|
void SensorDetectedNotification(int32_t aId, SensorsType aType,
|
|
|
|
float aRange, float aResolution,
|
|
|
|
float aPower, int32_t aMinPeriod,
|
|
|
|
int32_t aMaxPeriod,
|
|
|
|
SensorsTriggerMode aTriggerMode,
|
|
|
|
SensorsDeliveryMode aDeliveryMode) override
|
|
|
|
{
|
|
|
|
auto i = FindSensorIndexById(aId);
|
|
|
|
if (i == -1) {
|
|
|
|
// Add a new sensor...
|
|
|
|
i = mSensors.Length();
|
|
|
|
mSensors.AppendElement(SensorsSensor(aId, aType, aRange, aResolution,
|
|
|
|
aPower, aMinPeriod, aMaxPeriod,
|
|
|
|
aTriggerMode, aDeliveryMode));
|
|
|
|
} else {
|
|
|
|
// ...or update an existing one.
|
|
|
|
mSensors[i] = SensorsSensor(aId, aType, aRange, aResolution, aPower,
|
|
|
|
aMinPeriod, aMaxPeriod, aTriggerMode,
|
|
|
|
aDeliveryMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
mClasses[aType].UpdateFromSensor(mSensors[i]);
|
|
|
|
|
|
|
|
if (mClasses[aType].mActivated &&
|
|
|
|
mSensors[i].mDeliveryMode == DefaultSensorsDeliveryMode(aType)) {
|
|
|
|
// The new sensor's type is enabled, so enable sensor.
|
|
|
|
mPollInterface->EnableSensor(aId, nullptr);
|
|
|
|
mPollInterface->SetPeriod(mSensors[i].mId, DefaultSensorPeriod(aType),
|
|
|
|
nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SensorLostNotification(int32_t aId) override
|
|
|
|
{
|
|
|
|
auto i = FindSensorIndexById(aId);
|
|
|
|
if (i != -1) {
|
|
|
|
mSensors.RemoveElementAt(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EventNotification(int32_t aId, const SensorsEvent& aEvent) override
|
|
|
|
{
|
|
|
|
auto i = FindSensorIndexById(aId);
|
|
|
|
if (i == -1) {
|
|
|
|
HAL_ERR("Sensor %d not registered", aId);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SensorData sensorData;
|
|
|
|
auto rv = CreateSensorData(aEvent, mClasses[mSensors[i].mType],
|
|
|
|
sensorData);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
NotifySensorChange(sensorData);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
ssize_t FindSensorIndexById(int32_t aId) const
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < mSensors.Length(); ++i) {
|
|
|
|
if (mSensors[i].mId == aId) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t DefaultSensorPeriod(SensorsType aType) const
|
|
|
|
{
|
|
|
|
return aType == SENSORS_TYPE_ACCELEROMETER ? ACCELEROMETER_POLL_RATE
|
|
|
|
: DEFAULT_DEVICE_POLL_RATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
SensorsDeliveryMode DefaultSensorsDeliveryMode(SensorsType aType) const
|
|
|
|
{
|
|
|
|
if (aType == SENSORS_TYPE_PROXIMITY ||
|
|
|
|
aType == SENSORS_TYPE_SIGNIFICANT_MOTION) {
|
|
|
|
return SENSORS_DELIVERY_MODE_IMMEDIATE;
|
|
|
|
}
|
|
|
|
return SENSORS_DELIVERY_MODE_BEST_EFFORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
SensorType HardwareSensorToHalSensor(SensorsType aType) const
|
|
|
|
{
|
|
|
|
// FIXME: bug 802004, add proper support for the magnetic-field sensor.
|
|
|
|
switch (aType) {
|
|
|
|
case SENSORS_TYPE_ORIENTATION:
|
|
|
|
return SENSOR_ORIENTATION;
|
|
|
|
case SENSORS_TYPE_ACCELEROMETER:
|
|
|
|
return SENSOR_ACCELERATION;
|
|
|
|
case SENSORS_TYPE_PROXIMITY:
|
|
|
|
return SENSOR_PROXIMITY;
|
|
|
|
case SENSORS_TYPE_LIGHT:
|
|
|
|
return SENSOR_LIGHT;
|
|
|
|
case SENSORS_TYPE_GYROSCOPE:
|
|
|
|
return SENSOR_GYROSCOPE;
|
|
|
|
case SENSORS_TYPE_LINEAR_ACCELERATION:
|
|
|
|
return SENSOR_LINEAR_ACCELERATION;
|
|
|
|
case SENSORS_TYPE_ROTATION_VECTOR:
|
|
|
|
return SENSOR_ROTATION_VECTOR;
|
|
|
|
case SENSORS_TYPE_GAME_ROTATION_VECTOR:
|
|
|
|
return SENSOR_GAME_ROTATION_VECTOR;
|
|
|
|
default:
|
|
|
|
NS_NOTREACHED("Invalid sensors type");
|
|
|
|
}
|
|
|
|
return SENSOR_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
SensorAccuracyType HardwareStatusToHalAccuracy(SensorsStatus aStatus) const
|
|
|
|
{
|
|
|
|
return static_cast<SensorAccuracyType>(aStatus - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult CreateSensorData(const SensorsEvent& aEvent,
|
|
|
|
const SensorsSensorClass& aSensorClass,
|
|
|
|
SensorData& aSensorData) const
|
|
|
|
{
|
|
|
|
AutoTArray<float, 4> sensorValues;
|
|
|
|
|
|
|
|
auto sensor = HardwareSensorToHalSensor(aEvent.mType);
|
|
|
|
|
|
|
|
if (sensor == SENSOR_UNKNOWN) {
|
|
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
aSensorData.sensor() = sensor;
|
|
|
|
aSensorData.accuracy() = HardwareStatusToHalAccuracy(aEvent.mStatus);
|
|
|
|
aSensorData.timestamp() = aEvent.mTimestamp;
|
|
|
|
|
|
|
|
if (aSensorData.sensor() == SENSOR_ORIENTATION) {
|
|
|
|
// Bug 938035: transfer HAL data for orientation sensor to meet W3C spec
|
|
|
|
// ex: HAL report alpha=90 means East but alpha=90 means West in W3C spec
|
|
|
|
sensorValues.AppendElement(360.0 - radToDeg(aEvent.mData.mFloat[0]));
|
|
|
|
sensorValues.AppendElement(-radToDeg(aEvent.mData.mFloat[1]));
|
|
|
|
sensorValues.AppendElement(-radToDeg(aEvent.mData.mFloat[2]));
|
|
|
|
} else if (aSensorData.sensor() == SENSOR_ACCELERATION) {
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[0]);
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[1]);
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[2]);
|
|
|
|
} else if (aSensorData.sensor() == SENSOR_PROXIMITY) {
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[0]);
|
|
|
|
sensorValues.AppendElement(aSensorClass.mMinValue);
|
|
|
|
sensorValues.AppendElement(aSensorClass.mMaxValue);
|
|
|
|
} else if (aSensorData.sensor() == SENSOR_LINEAR_ACCELERATION) {
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[0]);
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[1]);
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[2]);
|
|
|
|
} else if (aSensorData.sensor() == SENSOR_GYROSCOPE) {
|
|
|
|
sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[0]));
|
|
|
|
sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[1]));
|
|
|
|
sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[2]));
|
|
|
|
} else if (aSensorData.sensor() == SENSOR_LIGHT) {
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[0]);
|
|
|
|
} else if (aSensorData.sensor() == SENSOR_ROTATION_VECTOR) {
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[0]);
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[1]);
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[2]);
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[3]);
|
|
|
|
} else if (aSensorData.sensor() == SENSOR_GAME_ROTATION_VECTOR) {
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[0]);
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[1]);
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[2]);
|
|
|
|
sensorValues.AppendElement(aEvent.mData.mFloat[3]);
|
|
|
|
}
|
|
|
|
|
|
|
|
aSensorData.values() = sensorValues;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
GonkSensorsPollInterface* mPollInterface;
|
|
|
|
nsTArray<SensorsSensor> mSensors;
|
|
|
|
SensorsSensorClass mClasses[SENSORS_NUM_TYPES];
|
|
|
|
};
|
|
|
|
|
|
|
|
static StaticAutoPtr<SensorsPollNotificationHandler> sPollNotificationHandler;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This is the notifiaction handler for the Sensors interface. If the backend
|
|
|
|
* crashes, we can restart it from here.
|
|
|
|
*/
|
|
|
|
class SensorsNotificationHandler final : public GonkSensorsNotificationHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SensorsNotificationHandler(GonkSensorsInterface* aInterface)
|
|
|
|
: mInterface(aInterface)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mInterface);
|
|
|
|
|
|
|
|
mInterface->SetNotificationHandler(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackendErrorNotification(bool aCrashed) override
|
|
|
|
{
|
|
|
|
// XXX: Bug 1206056: restart sensorsd
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
GonkSensorsInterface* mInterface;
|
|
|
|
};
|
|
|
|
|
|
|
|
static StaticAutoPtr<SensorsNotificationHandler> sNotificationHandler;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* |SensorsRegisterModuleResultHandler| implements the result-handler
|
|
|
|
* callback for registering the Poll service and activating the first
|
|
|
|
* sensors. If an error occures during the process, the result handler
|
|
|
|
* disconnects and closes the backend.
|
|
|
|
*/
|
|
|
|
class SensorsRegisterModuleResultHandler final
|
|
|
|
: public GonkSensorsRegistryResultHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SensorsRegisterModuleResultHandler(
|
|
|
|
uint32_t* aSensorsTypeActivated,
|
|
|
|
GonkSensorsInterface* aInterface)
|
|
|
|
: mSensorsTypeActivated(aSensorsTypeActivated)
|
|
|
|
, mInterface(aInterface)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mSensorsTypeActivated);
|
|
|
|
MOZ_ASSERT(mInterface);
|
|
|
|
}
|
|
|
|
void OnError(SensorsError aError) override
|
|
|
|
{
|
|
|
|
GonkSensorsRegistryResultHandler::OnError(aError); // print error message
|
|
|
|
Disconnect(); // Registering failed, so close the connection completely
|
|
|
|
}
|
|
|
|
void RegisterModule(uint32_t aProtocolVersion) override
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(!sPollNotificationHandler);
|
|
|
|
|
|
|
|
// Init, step 3: set notification handler for poll service and vice versa
|
|
|
|
auto pollInterface = mInterface->GetSensorsPollInterface();
|
|
|
|
if (!pollInterface) {
|
|
|
|
Disconnect();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (NS_FAILED(pollInterface->SetProtocolVersion(aProtocolVersion))) {
|
|
|
|
Disconnect();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sPollNotificationHandler =
|
|
|
|
new SensorsPollNotificationHandler(pollInterface);
|
|
|
|
|
|
|
|
// Init, step 4: activate sensors
|
|
|
|
for (int i = 0; i < SENSORS_NUM_TYPES; ++i) {
|
|
|
|
while (mSensorsTypeActivated[i]) {
|
|
|
|
sPollNotificationHandler->EnableSensorsByType(
|
|
|
|
static_cast<SensorsType>(i));
|
|
|
|
--mSensorsTypeActivated[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public:
|
|
|
|
void Disconnect()
|
|
|
|
{
|
|
|
|
class DisconnectResultHandler final : public GonkSensorsResultHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
void OnError(SensorsError aError)
|
|
|
|
{
|
|
|
|
GonkSensorsResultHandler::OnError(aError); // print error message
|
|
|
|
sNotificationHandler = nullptr;
|
|
|
|
}
|
|
|
|
void Disconnect() override
|
|
|
|
{
|
|
|
|
sNotificationHandler = nullptr;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
mInterface->Disconnect(new DisconnectResultHandler());
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
uint32_t* mSensorsTypeActivated;
|
|
|
|
GonkSensorsInterface* mInterface;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* |SensorsConnectResultHandler| implements the result-handler
|
|
|
|
* callback for starting the Sensors backend.
|
|
|
|
*/
|
|
|
|
class SensorsConnectResultHandler final : public GonkSensorsResultHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SensorsConnectResultHandler(
|
|
|
|
uint32_t* aSensorsTypeActivated,
|
|
|
|
GonkSensorsInterface* aInterface)
|
|
|
|
: mSensorsTypeActivated(aSensorsTypeActivated)
|
|
|
|
, mInterface(aInterface)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mSensorsTypeActivated);
|
|
|
|
MOZ_ASSERT(mInterface);
|
|
|
|
}
|
|
|
|
void OnError(SensorsError aError) override
|
|
|
|
{
|
|
|
|
GonkSensorsResultHandler::OnError(aError); // print error message
|
|
|
|
sNotificationHandler = nullptr;
|
|
|
|
}
|
|
|
|
void Connect() override
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
// Init, step 2: register poll service
|
|
|
|
auto registryInterface = mInterface->GetSensorsRegistryInterface();
|
|
|
|
if (!registryInterface) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
registryInterface->RegisterModule(
|
|
|
|
GonkSensorsPollModule::SERVICE_ID,
|
|
|
|
new SensorsRegisterModuleResultHandler(mSensorsTypeActivated,
|
|
|
|
mInterface));
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
uint32_t* mSensorsTypeActivated;
|
|
|
|
GonkSensorsInterface* mInterface;
|
|
|
|
};
|
|
|
|
|
|
|
|
static uint32_t sSensorsTypeActivated[SENSORS_NUM_TYPES];
|
|
|
|
|
|
|
|
static const SensorsType sSensorsType[] = {
|
|
|
|
[SENSOR_ORIENTATION] = SENSORS_TYPE_ORIENTATION,
|
|
|
|
[SENSOR_ACCELERATION] = SENSORS_TYPE_ACCELEROMETER,
|
|
|
|
[SENSOR_PROXIMITY] = SENSORS_TYPE_PROXIMITY,
|
|
|
|
[SENSOR_LINEAR_ACCELERATION] = SENSORS_TYPE_LINEAR_ACCELERATION,
|
|
|
|
[SENSOR_GYROSCOPE] = SENSORS_TYPE_GYROSCOPE,
|
|
|
|
[SENSOR_LIGHT] = SENSORS_TYPE_LIGHT,
|
|
|
|
[SENSOR_ROTATION_VECTOR] = SENSORS_TYPE_ROTATION_VECTOR,
|
|
|
|
[SENSOR_GAME_ROTATION_VECTOR] = SENSORS_TYPE_GAME_ROTATION_VECTOR
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
EnableSensorNotificationsDaemon(SensorType aSensor)
|
|
|
|
{
|
|
|
|
if ((aSensor < 0) ||
|
|
|
|
(aSensor > static_cast<ssize_t>(MOZ_ARRAY_LENGTH(sSensorsType)))) {
|
|
|
|
HAL_ERR("Sensor type %d not known", aSensor);
|
|
|
|
return; // Unsupported sensor type
|
|
|
|
}
|
|
|
|
|
|
|
|
auto interface = GonkSensorsInterface::GetInstance();
|
|
|
|
if (!interface) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sPollNotificationHandler) {
|
|
|
|
// Everythings already up and running; enable sensor type.
|
|
|
|
sPollNotificationHandler->EnableSensorsByType(sSensorsType[aSensor]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
++SaturateOpUint32(sSensorsTypeActivated[sSensorsType[aSensor]]);
|
|
|
|
|
|
|
|
if (sNotificationHandler) {
|
|
|
|
// We are in the middle of a pending start up; nothing else to do.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start up
|
|
|
|
|
|
|
|
MOZ_ASSERT(!sPollNotificationHandler);
|
|
|
|
MOZ_ASSERT(!sNotificationHandler);
|
|
|
|
|
|
|
|
sNotificationHandler = new SensorsNotificationHandler(interface);
|
|
|
|
|
|
|
|
// Init, step 1: connect to Sensors backend
|
|
|
|
interface->Connect(
|
|
|
|
sNotificationHandler,
|
|
|
|
new SensorsConnectResultHandler(sSensorsTypeActivated, interface));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
DisableSensorNotificationsDaemon(SensorType aSensor)
|
|
|
|
{
|
|
|
|
if ((aSensor < 0) ||
|
|
|
|
(aSensor > static_cast<ssize_t>(MOZ_ARRAY_LENGTH(sSensorsType)))) {
|
|
|
|
HAL_ERR("Sensor type %d not known", aSensor);
|
|
|
|
return; // Unsupported sensor type
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sPollNotificationHandler) {
|
|
|
|
// Everthings up and running; disable sensors type
|
|
|
|
sPollNotificationHandler->DisableSensorsByType(sSensorsType[aSensor]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We might be in the middle of a startup; decrement type's ref-counter.
|
|
|
|
--SaturateOpUint32(sSensorsTypeActivated[sSensorsType[aSensor]]);
|
|
|
|
|
|
|
|
// TODO: stop sensorsd if all sensors are disabled
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Public interface
|
|
|
|
//
|
|
|
|
|
|
|
|
// TODO: Remove in-Gecko sensors code. Until all devices' base
|
|
|
|
// images come with sensorsd installed, we have to support the
|
|
|
|
// in-Gecko implementation as well. So we test for the existance
|
|
|
|
// of the binary. If it's there, we use it. Otherwise we run the
|
|
|
|
// old code.
|
|
|
|
static bool
|
|
|
|
HasDaemon()
|
|
|
|
{
|
|
|
|
static bool tested;
|
|
|
|
static bool hasDaemon;
|
|
|
|
|
|
|
|
if (MOZ_UNLIKELY(!tested)) {
|
|
|
|
hasDaemon = !access("/system/bin/sensorsd", X_OK);
|
|
|
|
tested = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hasDaemon;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
EnableSensorNotifications(SensorType aSensor)
|
|
|
|
{
|
|
|
|
if (HasDaemon()) {
|
|
|
|
EnableSensorNotificationsDaemon(aSensor);
|
|
|
|
} else {
|
|
|
|
EnableSensorNotificationsInternal(aSensor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
DisableSensorNotifications(SensorType aSensor)
|
|
|
|
{
|
|
|
|
if (HasDaemon()) {
|
|
|
|
DisableSensorNotificationsDaemon(aSensor);
|
|
|
|
} else {
|
|
|
|
DisableSensorNotificationsInternal(aSensor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-06 06:41:15 +04:00
|
|
|
} // hal_impl
|
|
|
|
} // mozilla
|