diff --git a/adaptors/hybrisproximityadaptor/hybrisproximityadaptor.cpp b/adaptors/hybrisproximityadaptor/hybrisproximityadaptor.cpp index f1a3d9f4..00836b04 100644 --- a/adaptors/hybrisproximityadaptor/hybrisproximityadaptor.cpp +++ b/adaptors/hybrisproximityadaptor/hybrisproximityadaptor.cpp @@ -138,7 +138,7 @@ void HybrisProximityAdaptor::processSample(const sensors_event_t& data) ProximityData *d = buffer->nextSlot(); d->timestamp_ = quint64(data.timestamp * .001); bool near = false; - if (data.distance < maxRange) { + if (data.distance < maxRange()) { near = true; } d->withinProximity_ = near; diff --git a/core/hybrisadaptor.cpp b/core/hybrisadaptor.cpp index d5bd0793..3913e96f 100644 --- a/core/hybrisadaptor.cpp +++ b/core/hybrisadaptor.cpp @@ -83,172 +83,282 @@ #endif //#define SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR (20) -Q_GLOBAL_STATIC(HybrisManager, hybrisManager) - -HybrisManager::HybrisManager(QObject *parent) - : QObject(parent) - , device(NULL) - , sensorList(NULL) - , module(NULL) - , sensorsCount(0) - , sensorMap() - , registeredAdaptors() - , adaptorReaderTid(0) -{ - init(); +/* ========================================================================= * + * UTILITIES + * ========================================================================= */ + +static char const * +sensorTypeName(int type) +{ + switch(type) { + case SENSOR_TYPE_META_DATA: return "META_DATA"; + case SENSOR_TYPE_ACCELEROMETER: return "ACCELEROMETER"; + case SENSOR_TYPE_GEOMAGNETIC_FIELD: return "GEOMAGNETIC_FIELD"; + case SENSOR_TYPE_ORIENTATION: return "ORIENTATION"; + case SENSOR_TYPE_GYROSCOPE: return "GYROSCOPE"; + case SENSOR_TYPE_LIGHT: return "LIGHT"; + case SENSOR_TYPE_PRESSURE: return "PRESSURE"; + case SENSOR_TYPE_TEMPERATURE: return "TEMPERATURE"; + case SENSOR_TYPE_PROXIMITY: return "PROXIMITY"; + case SENSOR_TYPE_GRAVITY: return "GRAVITY"; + case SENSOR_TYPE_LINEAR_ACCELERATION: return "LINEAR_ACCELERATION"; + case SENSOR_TYPE_ROTATION_VECTOR: return "ROTATION_VECTOR"; + case SENSOR_TYPE_RELATIVE_HUMIDITY: return "RELATIVE_HUMIDITY"; + case SENSOR_TYPE_AMBIENT_TEMPERATURE: return "AMBIENT_TEMPERATURE"; + case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED: return "MAGNETIC_FIELD_UNCALIBRATED"; + case SENSOR_TYPE_GAME_ROTATION_VECTOR: return "GAME_ROTATION_VECTOR"; + case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED: return "GYROSCOPE_UNCALIBRATED"; + case SENSOR_TYPE_SIGNIFICANT_MOTION: return "SIGNIFICANT_MOTION"; + case SENSOR_TYPE_STEP_DETECTOR: return "STEP_DETECTOR"; + case SENSOR_TYPE_STEP_COUNTER: return "STEP_COUNTER"; + case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR: return "GEOMAGNETIC_ROTATION_VECTOR"; + case SENSOR_TYPE_HEART_RATE: return "HEART_RATE"; + case SENSOR_TYPE_TILT_DETECTOR: return "TILT_DETECTOR"; + case SENSOR_TYPE_WAKE_GESTURE: return "WAKE_GESTURE"; + case SENSOR_TYPE_GLANCE_GESTURE: return "GLANCE_GESTURE"; + case SENSOR_TYPE_PICK_UP_GESTURE: return "PICK_UP_GESTURE"; + case SENSOR_TYPE_WRIST_TILT_GESTURE: return "WRIST_TILT_GESTURE"; + } + + static char buf[32]; + snprintf(buf, sizeof buf, "type%d", type); + return buf; } -HybrisManager::~HybrisManager() +static void ObtainTemporaryWakeLock() { - closeAllSensors(); - if (adaptorReaderTid) { - sensordLogD() << "Canceling hal reader thread"; - int err = pthread_cancel(adaptorReaderTid); - if( err ) { - sensordLogC() << "Failed to cancel hal reader thread"; - } - else { - sensordLogD() << "Waiting for hal reader thread to exit"; - void *ret = 0; - struct timespec tmo = { 0, 0}; - clock_gettime(CLOCK_REALTIME, &tmo); - tmo.tv_sec += 3; - err = pthread_timedjoin_np(adaptorReaderTid, &ret, &tmo); - if( err ) { - sensordLogC() << "Hal reader thread did not exit"; - } else { - sensordLogD() << "Hal reader thread terminated"; - adaptorReaderTid = 0; - } + static bool triedToOpen = false; + static int wakeLockFd = -1; + + if (!triedToOpen) { + triedToOpen = true; + wakeLockFd = ::open("/sys/power/wake_lock", O_RDWR); + if (wakeLockFd == -1) { + sensordLogW() << "wake locks not available:" << ::strerror(errno); } - if (adaptorReaderTid) { - /* The reader thread is stuck at android hal blob. - * Continuing would be likely to release resourse - * still in active use and lead to segfaulting. - * Resort to doing a quick and dirty exit. */ - _exit(EXIT_FAILURE); + } + + if (wakeLockFd != -1) { + sensordLogD() << "wake lock to guard sensor data io"; + static const char m[] = "sensorfwd_pass_data 1000000000\n"; + if (::write(wakeLockFd, m, sizeof m - 1) == -1) { + sensordLogW() << "wake locking failed:" << ::strerror(errno); + ::close(wakeLockFd), wakeLockFd = -1; } } } -HybrisManager *HybrisManager::instance() +/* ========================================================================= * + * HybrisSensorState + * ========================================================================= */ + +HybrisSensorState::HybrisSensorState() + : m_minDelay(0) + , m_maxDelay(0) + , m_delay(-1) + , m_active(-1) { - HybrisManager *priv = hybrisManager(); - return priv; } -void HybrisManager::init() +HybrisSensorState::~HybrisSensorState() { - int errorCode = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); - if (errorCode != 0) { - qDebug() << "hw_get_module() failed" << strerror(-errorCode); +} + +/* ========================================================================= * + * HybrisManager + * ========================================================================= */ + +Q_GLOBAL_STATIC(HybrisManager, hybrisManager) + +HybrisManager::HybrisManager(QObject *parent) + : QObject(parent) + , m_initialized(false) + , m_registeredAdaptors() + , m_halModule(NULL) + , m_halDevice(NULL) + , m_halSensorCount(0) + , m_halSensorArray(NULL) + , m_halSensorState(NULL) + , m_halIndexOfType() + , m_halIndexOfHandle() + , m_halEventReaderTid(0) +{ + int err; + + /* Open android sensor plugin */ + err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, + (hw_module_t const**)&m_halModule); + if (err != 0) { + m_halModule = 0; + sensordLogW() << "hw_get_module() failed" << strerror(-err); return ; } - if (!openSensors()) { - sensordLogW() << "Cannot open sensors"; + /* Open android sensor device */ + err = sensors_open(&m_halModule->common, &m_halDevice); + if (err != 0) { + m_halDevice = 0; + sensordLogW() << "sensors_open() failed:" << strerror(-err); return; } - sensorsCount = module->get_sensors_list(module, &sensorList); + /* Get static sensor information */ + m_halSensorCount = m_halModule->get_sensors_list(m_halModule, &m_halSensorArray); + + /* Reserve space for sensor state data */ + m_halSensorState = new HybrisSensorState[m_halSensorCount]; + + /* Select and initialize sensors to be used */ + for (int i = 0 ; i < m_halSensorCount ; i++) { + /* Always do handle -> index mapping */ + m_halIndexOfHandle.insert(m_halSensorArray[i].handle, i); - for (int i = 0 ; i < sensorsCount ; i++) { bool use = true; // Assumption: The primary sensor variants that we want to // use are listed before the secondary ones that we want // to ignore -> Use the 1st entry found for each sensor type. - if( sensorMap.contains(sensorList[i].type) ) { + if (m_halIndexOfType.contains(m_halSensorArray[i].type)) { use = false; } // some devices have compass and compass raw, // ignore compass raw. compass has range 360 - if (sensorList[i].type == SENSOR_TYPE_ORIENTATION && - sensorList[i].maxRange != 360) { + if (m_halSensorArray[i].type == SENSOR_TYPE_ORIENTATION && + m_halSensorArray[i].maxRange != 360) { use = false; } - sensordLogW() << Q_FUNC_INFO + sensordLogD() << Q_FUNC_INFO << (use ? "SELECT" : "IGNORE") - << "type:" << sensorList[i].type - << "name:" << (sensorList[i].name ?: "n/a"); + << "type:" << m_halSensorArray[i].type + << "name:" << (m_halSensorArray[i].name ?: "n/a"); if (use) { - sensorMap.insert(sensorList[i].type, i); - } + // min/max delay is specified in [us] -> convert to [ms] + int minDelay = (m_halSensorArray[i].minDelay + 999) / 1000; + int maxDelay = (m_halSensorArray[i].maxDelay + 999) / 1000; + + // Positive minDelay means delay /can/ be set - but depending + // on sensor hal implementation it can also mean that some + // delay /must/ be set or the sensor does not start reporting + // despite being enabled -> as an protection agains clients + // failing to explicitly set delays / using delays that would + // get rejected by upper levels of sensorfwd logic -> setup + // 200 ms delay (capped to reported min/max range). + if (minDelay >= 0) { + if (maxDelay < minDelay) + maxDelay = minDelay; + + int delay = minDelay ? 200 : 0; + if (delay < minDelay) + delay = minDelay; + else if (delay > maxDelay ) + delay = maxDelay; + + m_halSensorState[i].m_minDelay = minDelay; + m_halSensorState[i].m_maxDelay = maxDelay; + + halSetActive(m_halSensorArray[i].handle, true); + halSetDelay(m_halSensorArray[i].handle, delay); + } + m_halIndexOfType.insert(m_halSensorArray[i].type, i); + + /* Make sure all sensors are initially in stopped state */ + halSetActive(m_halSensorArray[i].handle, false); } - int err = pthread_create(&adaptorReaderTid, 0, adaptorReaderThread, this); + /* Start android sensor event reader */ + err = pthread_create(&m_halEventReaderTid, 0, halEventReaderThread, this); if (err) { - adaptorReaderTid = 0; + m_halEventReaderTid = 0; sensordLogC() << "Failed to start hal reader thread"; - } else { - sensordLogD() << "Hal reader thread started"; + return; } + sensordLogD() << "Hal reader thread started"; + + m_initialized = true; } -int HybrisManager::handleForType(int sensorType) +HybrisManager::~HybrisManager() { - if (sensorMap.contains(sensorType)) - return sensorList[sensorMap[sensorType]].handle; + sensordLogD() << "stop all sensors"; + foreach (HybrisAdaptor *adaptor, m_registeredAdaptors.values()) { + adaptor->stopSensor(); + } - sensordLogW() << Q_FUNC_INFO << "No sensor of type:" << sensorType; - return -1; + if (m_halDevice) { + sensordLogD() << "close sensor device"; + int errorCode = sensors_close(m_halDevice); + if (errorCode != 0) { + sensordLogW() << "sensors_close() failed:" << strerror(-errorCode); + } + m_halDevice = NULL; + } + + if (m_halEventReaderTid) { + sensordLogD() << "Canceling hal reader thread"; + int err = pthread_cancel(m_halEventReaderTid); + if (err) { + sensordLogC() << "Failed to cancel hal reader thread"; + } else { + sensordLogD() << "Waiting for hal reader thread to exit"; + void *ret = 0; + struct timespec tmo = { 0, 0}; + clock_gettime(CLOCK_REALTIME, &tmo); + tmo.tv_sec += 3; + err = pthread_timedjoin_np(m_halEventReaderTid, &ret, &tmo); + if (err) { + sensordLogC() << "Hal reader thread did not exit"; + } else { + sensordLogD() << "Hal reader thread terminated"; + m_halEventReaderTid = 0; + } + } + if (m_halEventReaderTid) { + /* The reader thread is stuck at android hal blob. + * Continuing would be likely to release resourse + * still in active use and lead to segfaulting. + * Resort to doing a quick and dirty exit. */ + _exit(EXIT_FAILURE); + } + } + delete[] m_halSensorState; } -int HybrisManager::maxRange(int sensorType) +HybrisManager *HybrisManager::instance() { - if (sensorMap.contains(sensorType)) - return sensorList[sensorMap[sensorType]].maxRange; - return 0; + HybrisManager *priv = hybrisManager(); + return priv; } -int HybrisManager::minDelay(int sensorType) +int HybrisManager::halHandleForType(int sensorType) const { - int res = 0; - if (sensorMap.contains(sensorType)) { - res = sensorList[sensorMap[sensorType]].minDelay; - // us -> ms, round up - res = (res + 999) / 1000; - } - return res; + int index = halIndexForType(sensorType); + return (index < 0) ? -1 : m_halSensorArray[index].handle; } -int HybrisManager::resolution(int sensorType) +int HybrisManager::halIndexForHandle(int handle) const { - if (sensorMap.contains(sensorType)) - return sensorList[sensorMap[sensorType]].resolution; - return 0; + int index = m_halIndexOfHandle.value(handle, -1); + if (index == -1) + sensordLogW("HYBRIS CTL invalid sensor handle: %d", handle); + return index; } -bool HybrisManager::setDelay(int sensorHandle, int interval) +int HybrisManager::halIndexForType(int sensorType) const { - bool ok = true; - if (interval > 0) { - int result = device->setDelay(device, sensorHandle, interval); - if (result < 0) { - sensordLogW() << "setDelay() failed" << strerror(-result); - ok = false; - } - } - QList list; - list = registeredAdaptors.values(); - for (int i = 0; i < list.count(); i++) { - if (list.at(i)->sensorHandle == sensorHandle) { - list.at(i)->sendInitialData(); - } - } - - return ok; + int index = m_halIndexOfType.value(sensorType, -1); + if (index == -1) + sensordLogW("HYBRIS CTL invalid sensor type: %d", sensorType); + return index; } void HybrisManager::startReader(HybrisAdaptor *adaptor) { - if (registeredAdaptors.values().contains(adaptor)) { - sensordLogD() << "activating " << adaptor->name() << adaptor->sensorHandle; - int error = device->activate(device, adaptor->sensorHandle, 1); - if (error != 0) { - sensordLogW() <name() << adaptor->m_sensorHandle; + if (!halSetActive(adaptor->m_sensorHandle, true)) { + sensordLogW() <setValid(false); } } @@ -256,328 +366,364 @@ void HybrisManager::startReader(HybrisAdaptor *adaptor) void HybrisManager::stopReader(HybrisAdaptor *adaptor) { - QList list; - list = registeredAdaptors.values(); - bool okToStop = true; - - for (int i = 0; i < list.count(); i++) { - if (list.at(i) == adaptor && !list.at(i)->isRunning()) { + if (m_registeredAdaptors.values().contains(adaptor)) { sensordLogD() << "deactivating " << adaptor->name(); - int error = device->activate(device, adaptor->sensorHandle, 0); - if (error != 0) { - sensordLogW() <m_sensorHandle, false)) { + sensordLogW() <shouldBeRunning_) { - okToStop = false; - } } - qDebug() << "okToStop" << okToStop; } -bool HybrisManager::resumeReader(HybrisAdaptor *adaptor) +void HybrisManager::processSample(const sensors_event_t& data) { - sensordLogD() << Q_FUNC_INFO << adaptor->id() - << adaptor->deviceStandbyOverride() - << adaptor->isRunning(); //alwaysOn - - if (!adaptor->isRunning()) { - sensordLogD() << "activating for resume" << adaptor->name(); - int error = device->activate(device, adaptor->sensorHandle, 1); - if (error != 0) { - sensordLogW() <isRunning()) { + adaptor->processSample(data); } } - return true; } -void HybrisManager::standbyReader(HybrisAdaptor *adaptor) +void HybrisManager::registerAdaptor(HybrisAdaptor *adaptor) { - sensordLogD() << Q_FUNC_INFO << adaptor->id() - << adaptor->deviceStandbyOverride() - << adaptor->isRunning(); //alwaysOn - - if (adaptor->isRunning() && !adaptor->deviceStandbyOverride()) { - sensordLogD() << "deactivating for standby" << adaptor->name(); - int error = device->activate(device, adaptor->sensorHandle, 0); - if (error != 0) { - sensordLogW() <isValid()) { + m_registeredAdaptors.insertMulti(adaptor->m_sensorType, adaptor); } } -bool HybrisManager::openSensors() +float HybrisManager::halGetMaxRange(int handle) const { - if (!device) { - sensordLogD() << "Calling sensors_open"; - int errorCode = sensors_open(&module->common, &device); - if (errorCode != 0) { - sensordLogW() << "sensors_open() failed:" << strerror(-errorCode); - device = NULL; - } + float range = 0; + int index = halIndexForHandle(handle); + + if (index != -1) { + const struct sensor_t *sensor = &m_halSensorArray[index]; + + range = sensor->maxRange; + sensordLogT("HYBRIS CTL getMaxRange(%d=%s) -> %g", + sensor->handle, sensorTypeName(sensor->type), range); } - return (device != NULL); + return range; } -bool HybrisManager::closeSensors() +float HybrisManager::halGetResolution(int handle) const { - if (device) { - foreach (HybrisAdaptor *adaptor, registeredAdaptors.values()) { - if (adaptor->isRunning()) { - sensordLogW() << Q_FUNC_INFO << "still running:" << adaptor; - return false; - } - } + float resolution = 0; + int index = halIndexForHandle(handle); - sensordLogD() << "Calling sensors_close"; - int errorCode = sensors_close(device); - if (errorCode != 0) { - sensordLogW() << "sensors_close() failed:" << strerror(-errorCode); - } + if (index != -1) { + const struct sensor_t *sensor = &m_halSensorArray[index]; + + resolution = sensor->resolution; + sensordLogT("HYBRIS CTL getResolution(%d=%s) -> %g", + sensor->handle, sensorTypeName(sensor->type), resolution); } - device = NULL; - return true; + return resolution; } -void HybrisManager::closeAllSensors() +int HybrisManager::halGetMinDelay(int handle) const { - QList list; - list = registeredAdaptors.values(); + int delay = 0; + int index = halIndexForHandle(handle); - for (int i = 0; i < list.count(); i++) { - if (list.at(i)->isRunning()) - list.at(i)->stopSensor(); - } + if (index != -1) { + const struct sensor_t *sensor = &m_halSensorArray[index]; + HybrisSensorState *state = &m_halSensorState[index]; - if (!closeSensors()) { - sensordLogW() << "Cannot close sensors"; + delay = state->m_minDelay; + sensordLogT("HYBRIS CTL getMinDelay(%d=%s) -> %d", + sensor->handle, sensorTypeName(sensor->type), delay); } + + return delay; } -void HybrisManager::processSample(const sensors_event_t& data) +int HybrisManager::halGetMaxDelay(int handle) const { - foreach (HybrisAdaptor *adaptor, registeredAdaptors.values(data.type)) { - if (adaptor->isRunning()) { - adaptor->processSample(data); - } + int delay = 0; + int index = halIndexForHandle(handle); + + if (index != -1) { + const struct sensor_t *sensor = &m_halSensorArray[index]; + HybrisSensorState *state = &m_halSensorState[index]; + + delay = state->m_maxDelay; + sensordLogT("HYBRIS CTL getMaxDelay(%d=%s) -> %d", + sensor->handle, sensorTypeName(sensor->type), delay); } + + return delay; } -void HybrisManager::registerAdaptor(HybrisAdaptor *adaptor) +int HybrisManager::halGetDelay(int handle) const { - if (!registeredAdaptors.values().contains(adaptor) && adaptor->isValid()) { - registeredAdaptors.insertMulti(adaptor->sensorType, adaptor); - } -} + int delay = 0; + int index = halIndexForHandle(handle); -////////////////////////////////// -HybrisAdaptor::HybrisAdaptor(const QString& id, int type) - : DeviceAdaptor(id), - sensorType(type), - cachedInterval(50), - inStandbyMode_(false), - running_(false) -{ - sensorHandle = hybrisManager()->handleForType(sensorType); - if (sensorHandle == -1) { - qDebug() << Q_FUNC_INFO <<"no such sensor" << id; - setValid(false); - return; + if (index != -1) { + const struct sensor_t *sensor = &m_halSensorArray[index]; + HybrisSensorState *state = &m_halSensorState[index]; + + delay = state->m_delay; + sensordLogT("HYBRIS CTL getDelay(%d=%s) -> %d", + sensor->handle, sensorTypeName(sensor->type), delay); } - hybrisManager()->registerAdaptor(this); - init(); - introduceAvailableInterval(DataRange(minDelay, 1000, 0)); - introduceAvailableDataRange(DataRange(-(maxRange*.5), (maxRange*.5), 1)); + return delay; } -HybrisAdaptor::~HybrisAdaptor() +bool HybrisManager::halSetDelay(int handle, int delay_ms) { -} + bool success = false; + int index = halIndexForHandle(handle); -void HybrisAdaptor::init() -{ - maxRange = hybrisManager()->maxRange(sensorType); - minDelay = hybrisManager()->minDelay(sensorType); - if (minDelay > 1000) - minDelay = 0; - resolution = hybrisManager()->resolution(sensorType); -} + if (index != -1) { + const struct sensor_t *sensor = &m_halSensorArray[index]; + HybrisSensorState *state = &m_halSensorState[index]; -bool HybrisAdaptor::addSensorType(int type) -{ - sensorIds.append(type); - return true; -} + if (state->m_delay == delay_ms) { + sensordLogT("HYBRIS CTL setDelay(%d=%s, %d) -> no-change", + sensor->handle, sensorTypeName(sensor->type), delay_ms); + } else { + int64_t delay_ns = delay_ms * 1000LL * 1000LL; + int error = m_halDevice->setDelay(m_halDevice, sensor->handle, delay_ns); + if (error) { + sensordLogW("HYBRIS CTL setDelay(%d=%s, %d) -> %d=%s", + sensor->handle, sensorTypeName(sensor->type), delay_ms, + error, strerror(error)); + } else { + sensordLogD("HYBRIS CTL setDelay(%d=%s, %d) -> success", + sensor->handle, sensorTypeName(sensor->type), delay_ms); + state->m_delay = delay_ms; + success = true; + } + } + } -bool HybrisAdaptor::startAdaptor() -{ - if (!isValid()) - return false; - return hybrisManager()->openSensors(); + return success; } -bool HybrisAdaptor::isRunning() const +bool HybrisManager::halGetActive(int handle) const { - return running_; -} + bool active = false; + int index = halIndexForHandle(handle); -void HybrisAdaptor::stopAdaptor() -{ - if (getAdaptedSensor()->isRunning()) - stopSensor(); - hybrisManager()->closeSensors(); + if (index != -1) { + const struct sensor_t *sensor = &m_halSensorArray[index]; + HybrisSensorState *state = &m_halSensorState[index]; + + active = (state->m_active > 0); + sensordLogT("HYBRIS CTL getActive(%d=%s) -> %s", + sensor->handle, sensorTypeName(sensor->type), + active ? "true" : "false"); + } + return active; } -bool HybrisAdaptor::startSensor() +bool HybrisManager::halSetActive(int handle, bool active) { - AdaptedSensorEntry *entry = getAdaptedSensor(); - if (entry == NULL) { - qDebug() << "Sensor not found: " << name(); - return false; - } + bool success = false; + int index = halIndexForHandle(handle); - // Increase listener count - entry->addReference(); + if (index != -1) { + const struct sensor_t *sensor = &m_halSensorArray[index]; + HybrisSensorState *state = &m_halSensorState[index]; - /// Check from entry - if (isRunning()) { - qDebug() << Q_FUNC_INFO << "already running"; - shouldBeRunning_ = true; - return false; + if (state->m_active == active) { + sensordLogT("HYBRIS CTL setActive%d=%s, %s) -> no-change", + sensor->handle, sensorTypeName(sensor->type), active ? "true" : "false"); + success = true; + } else { + int error = m_halDevice->activate(m_halDevice, sensor->handle, active); + if (error) { + sensordLogW("HYBRIS CTL setActive%d=%s, %s) -> %d=%s", + sensor->handle, sensorTypeName(sensor->type), active ? "true" : "false", + error, strerror(error)); + } else { + sensordLogD("HYBRIS CTL setActive%d=%s, %s) -> success", + sensor->handle, sensorTypeName(sensor->type), active ? "true" : "false"); + state->m_active = active; + success = true; + } + if (state->m_active == true && state->m_delay != -1) { + sensordLogD("HYBRIS CTL FORCE DELAY UPDATE"); + int delay_ms = state->m_delay; + state->m_delay = -1; + halSetDelay(handle, delay_ms); + } + } } + return success; +} - // Do not open if in standby mode. - if (inStandbyMode_ && !deviceStandbyOverride()) { - qDebug() << Q_FUNC_INFO << "inStandbyMode_ true"; - return false; - } +void *HybrisManager::halEventReaderThread(void *aptr) +{ + HybrisManager *manager = static_cast(aptr); + static const size_t numEvents = 16; + sensors_event_t buffer[numEvents]; + /* Async cancellation, but disabled */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0); + /* Leave INT/TERM signal processing up to the main thread */ + sigset_t ss; + sigemptyset(&ss); + sigaddset(&ss, SIGINT); + sigaddset(&ss, SIGTERM); + pthread_sigmask(SIG_BLOCK, &ss, 0); + /* Loop until explicitly canceled */ + for( ;; ) { + /* Async cancellation point at android hal poll() */ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0); + int numberOfEvents = manager->m_halDevice->poll(manager->m_halDevice, buffer, numEvents); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); + /* Rate limit in poll() error situations */ + if (numberOfEvents < 0) { + sensordLogW() << "android device->poll() failed" << strerror(-numberOfEvents); + struct timespec ts = { 1, 0 }; // 1000 ms + do { } while (nanosleep(&ts, &ts) == -1 && errno == EINTR); + continue; + } + /* Process received events */ + bool blockSuspend = false; + bool errorInInput = false; + for (int i = 0; i < numberOfEvents; i++) { + const sensors_event_t& data = buffer[i]; - shouldBeRunning_ = true; - /// We are waking up from standby or starting fresh, no matter - inStandbyMode_ = false; + sensordLogT("HYBRIS EVE %s", sensorTypeName(data.type)); - if (!startReaderThread()) { - entry->removeReference(); - entry->setIsRunning(false); - running_ = false; - shouldBeRunning_ = false; - return false; + if (data.version != sizeof(sensors_event_t)) { + sensordLogW()<< QString("incorrect event version (version=%1, expected=%2").arg(data.version).arg(sizeof(sensors_event_t)); + errorInInput = true; + } + if (data.type == SENSOR_TYPE_PROXIMITY) { + blockSuspend = true; + } + // FIXME: is this thread safe? + manager->processSample(data); + } + /* Suspend proof sensor reporting that could occur in display off */ + if (blockSuspend) { + ObtainTemporaryWakeLock(); + } + /* Rate limit after receiving erraneous events */ + if (errorInInput) { + struct timespec ts = { 0, 50 * 1000 * 1000 }; // 50 ms + do { } while (nanosleep(&ts, &ts) == -1 && errno == EINTR); + } } - - entry->setIsRunning(true); - running_ = true; - shouldBeRunning_ = true; - - return true; + return 0; } -void HybrisAdaptor::stopSensor() -{ - AdaptedSensorEntry *entry = getAdaptedSensor(); +/* ========================================================================= * + * HybrisAdaptor + * ========================================================================= */ - if (entry == NULL) { - sensordLogW() << "Sensor not found " << name(); +HybrisAdaptor::HybrisAdaptor(const QString& id, int type) + : DeviceAdaptor(id) + , m_inStandbyMode(false) + , m_isRunning(false) + , m_shouldBeRunning(false) + , m_sensorHandle(-1) + , m_sensorType(type) +{ + m_sensorHandle = hybrisManager()->halHandleForType(m_sensorType); + if (m_sensorHandle == -1) { + sensordLogW() << Q_FUNC_INFO <<"no such sensor" << id; + setValid(false); return; } - qDebug() << "shouldBeRunning_" << shouldBeRunning_ - << "inStandbyMode_" << inStandbyMode_ - << "reference count" << entry->referenceCount(); - if (!shouldBeRunning_) { - return; - } + hybrisManager()->registerAdaptor(this); +} - entry->removeReference(); - if (entry->referenceCount() <= 0) { - entry->setIsRunning(false); - running_ = false; - shouldBeRunning_ = false; - inStandbyMode_ = false; - if (!inStandbyMode_) { - stopReaderThread(); - } - } +HybrisAdaptor::~HybrisAdaptor() +{ } -bool HybrisAdaptor::standby() +void HybrisAdaptor::init() +{ + introduceAvailableDataRange(DataRange(minRange(), maxRange(), resolution())); + introduceAvailableInterval(DataRange(minInterval(), maxInterval(), 0)); +} + +void HybrisAdaptor::sendInitialData() +{ + // virtual dummy + // used for ps/als initial value hacks +} + +bool HybrisAdaptor::writeToFile(const QByteArray& path, const QByteArray& content) { - sensordLogD() << "Adaptor '" << id() << "' requested to go to standby" << "deviceStandbyOverride" << deviceStandbyOverride(); - if (inStandbyMode_ && deviceStandbyOverride()) { - sensordLogD() << "Adaptor '" << id() << "' not going to standby: already in standby"; + sensordLogT() << "Writing to '" << path << ": " << content; + QFile file(path); + if (!file.open(QIODevice::WriteOnly)) + { + sensordLogW() << "Failed to open '" << path << "': " << file.errorString(); return false; } - - if (!isRunning()) { - sensordLogD() << "Adaptor '" << id() << "' not going to standby: not running"; + if (file.write(content.constData(), content.size()) == -1) + { + sensordLogW() << "Failed to write to '" << path << "': " << file.errorString(); + file.close(); return false; } - inStandbyMode_ = true; - hybrisManager()->standbyReader(this); - running_ = deviceStandbyOverride(); - + file.close(); return true; } -bool HybrisAdaptor::resume() +/* ------------------------------------------------------------------------- * + * range + * ------------------------------------------------------------------------- */ + +qreal HybrisAdaptor::minRange() const { - sensordLogD() << "Adaptor '" << id() << "' requested to resume from standby"; - sensordLogD() << "deviceStandbyOverride" << deviceStandbyOverride(); + return 0; +} - // Don't resume if not in standby - if (!inStandbyMode_ && !deviceStandbyOverride()) { - sensordLogD() << "Adaptor '" << id() << "' not resuming: not in standby"; - return false; - } +qreal HybrisAdaptor::maxRange() const +{ + return hybrisManager()->halGetMaxRange(m_sensorHandle); +} - if (!shouldBeRunning_) { - sensordLogD() << "Adaptor '" << id() << "' not resuming from standby: not running"; - return false; - } +qreal HybrisAdaptor::resolution() const +{ + return hybrisManager()->halGetResolution(m_sensorHandle); +} - sensordLogD() << "Adaptor '" << id() << "' resuming from standby"; - inStandbyMode_ = false; +/* ------------------------------------------------------------------------- * + * interval + * ------------------------------------------------------------------------- */ - if (!hybrisManager()->resumeReader(this)) { - sensordLogW() << "Adaptor '" << id() << "' failed to resume from standby!"; - return false; - } - running_ = true; +unsigned int HybrisAdaptor::minInterval() const +{ + return hybrisManager()->halGetMinDelay(m_sensorHandle); +} - return true; +unsigned int HybrisAdaptor::maxInterval() const +{ + return hybrisManager()->halGetMaxDelay(m_sensorHandle); } unsigned int HybrisAdaptor::interval() const { - return cachedInterval; + return hybrisManager()->halGetDelay(m_sensorHandle); } -bool HybrisAdaptor::setInterval(const unsigned int value, const int /*sessionId*/) -{ // 1000000 - cachedInterval = value; - bool ok; - qreal ns = value * 1000000; // ms to ns - ok = hybrisManager()->setDelay(sensorHandle, ns); +bool HybrisAdaptor::setInterval(const unsigned int value, const int sessionId) +{ + Q_UNUSED(sessionId); + + bool ok = hybrisManager()->halSetDelay(m_sensorHandle, value); + if (!ok) { - qDebug() << Q_FUNC_INFO << "setInterval not ok"; + sensordLogW() << Q_FUNC_INFO << "setInterval not ok"; + } else { + sendInitialData(); } - return ok; -} -void HybrisAdaptor::stopReaderThread() -{ - hybrisManager()->stopReader(this); - running_ = false; -} - -bool HybrisAdaptor::startReaderThread() -{ - running_ = true; - hybrisManager()->startReader(this); - return true; + return ok; } unsigned int HybrisAdaptor::evaluateIntervalRequests(int& sessionId) const @@ -605,100 +751,97 @@ unsigned int HybrisAdaptor::evaluateIntervalRequests(int& sessionId) const return highestValue > 0 ? highestValue : defaultInterval(); } -bool HybrisAdaptor::writeToFile(const QByteArray& path, const QByteArray& content) +/* ------------------------------------------------------------------------- * + * start/stop adaptor + * ------------------------------------------------------------------------- */ + +bool HybrisAdaptor::startAdaptor() { - sensordLogT() << "Writing to '" << path << ": " << content; - QFile file(path); - if (!file.open(QIODevice::WriteOnly)) - { - sensordLogW() << "Failed to open '" << path << "': " << file.errorString(); - return false; + return isValid(); +} + +void HybrisAdaptor::stopAdaptor() +{ + if (getAdaptedSensor()->isRunning()) + stopSensor(); +} + +/* ------------------------------------------------------------------------- * + * start/stop sensor + * ------------------------------------------------------------------------- */ + +bool HybrisAdaptor::isRunning() const +{ + return m_isRunning; +} + +void HybrisAdaptor::evaluateSensor() +{ + // Get listener object + AdaptedSensorEntry *entry = getAdaptedSensor(); + if (entry == NULL) { + sensordLogW() << Q_FUNC_INFO << "Sensor not found: " << name(); + return; } - if (file.write(content.constData(), content.size()) == -1) - { - sensordLogW() << "Failed to write to '" << path << "': " << file.errorString(); - file.close(); - return false; + + // Check policy + bool runningAllowed = (deviceStandbyOverride() || !m_inStandbyMode); + + // Target state + bool startRunning = m_shouldBeRunning && runningAllowed; + + if (m_isRunning != startRunning) { + if ((m_isRunning = startRunning)) { + hybrisManager()->startReader(this); + if (entry->addReference() == 1) { + entry->setIsRunning(true); + } + } else { + if (entry->removeReference() == 0) { + entry->setIsRunning(false); + } + hybrisManager()->stopReader(this); + } + sensordLogT() << Q_FUNC_INFO << "entry" << entry->name() + << "refs:" << entry->referenceCount() << "running:" << entry->isRunning(); } +} - file.close(); +bool HybrisAdaptor::startSensor() +{ + if (!m_shouldBeRunning) { + m_shouldBeRunning = true; + sensordLogT("%s m_shouldBeRunning = %d", sensorTypeName(m_sensorType), m_shouldBeRunning); + evaluateSensor(); + } return true; } -static void ObtainTemporaryWakeLock() +void HybrisAdaptor::stopSensor() { - static bool triedToOpen = false; - static int wakeLockFd = -1; - - if (!triedToOpen) { - triedToOpen = true; - wakeLockFd = ::open("/sys/power/wake_lock", O_RDWR); - if (wakeLockFd == -1) { - sensordLogW() << "wake locks not available:" << ::strerror(errno); - } + if (m_shouldBeRunning) { + m_shouldBeRunning = false; + sensordLogT("%s m_shouldBeRunning = %d", sensorTypeName(m_sensorType), m_shouldBeRunning); + evaluateSensor(); } +} - if (wakeLockFd != -1) { - sensordLogD() << "wake lock to guard sensor data io"; - static const char m[] = "sensorfwd_pass_data 1000000000\n"; - if( ::write(wakeLockFd, m, sizeof m - 1) == -1 ) { - sensordLogW() << "wake locking failed:" << ::strerror(errno); - ::close(wakeLockFd), wakeLockFd = -1; - } +bool HybrisAdaptor::standby() +{ + if (!m_inStandbyMode) { + m_inStandbyMode = true; + sensordLogT("%s m_inStandbyMode = %d", sensorTypeName(m_sensorType), m_inStandbyMode); + evaluateSensor(); } + return true; } -void *HybrisManager::adaptorReaderThread(void *aptr) +bool HybrisAdaptor::resume() { - HybrisManager *manager = static_cast(aptr); - static const size_t numEvents = 16; - sensors_event_t buffer[numEvents]; - /* Async cancellation, but disabled */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); - pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0); - /* Leave INT/TERM signal processing up to the main thread */ - sigset_t ss; - sigemptyset(&ss); - sigaddset(&ss, SIGINT); - sigaddset(&ss, SIGTERM); - pthread_sigmask(SIG_BLOCK, &ss, 0); - /* Loop until explicitly canceled */ - for( ;; ) { - /* Async cancellation point at android hal poll() */ - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0); - int numberOfEvents = manager->device->poll(manager->device, buffer, numEvents); - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); - /* Rate limit in poll() error situations */ - if (numberOfEvents < 0) { - sensordLogW() << "android device->poll() failed" << strerror(-numberOfEvents); - struct timespec ts = { 1, 0 }; // 1000 ms - do { } while( nanosleep(&ts, &ts) == -1 && errno == EINTR ); - continue; - } - /* Process received events */ - bool blockSuspend = false; - bool errorInInput = false; - for (int i = 0; i < numberOfEvents; i++) { - const sensors_event_t& data = buffer[i]; - if (data.version != sizeof(sensors_event_t)) { - sensordLogW()<< QString("incorrect event version (version=%1, expected=%2").arg(data.version).arg(sizeof(sensors_event_t)); - errorInInput = true; - } - if (data.type == SENSOR_TYPE_PROXIMITY) { - blockSuspend = true; - } - // FIXME: is this thread safe? - manager->processSample(data); - } - /* Suspend proof sensor reporting that could occur in display off */ - if (blockSuspend) { - ObtainTemporaryWakeLock(); - } - /* Rate limit after receiving erraneous events */ - if (errorInInput) { - struct timespec ts = { 0, 50 * 1000 * 1000 }; // 50 ms - do { } while( nanosleep(&ts, &ts) == -1 && errno == EINTR ); - } + if (m_inStandbyMode) { + m_inStandbyMode = false; + sensordLogT("%s m_inStandbyMode = %d", sensorTypeName(m_sensorType), m_inStandbyMode); + evaluateSensor(); } - return 0; + return true; } diff --git a/core/hybrisadaptor.h b/core/hybrisadaptor.h index e530a7ad..389d6948 100644 --- a/core/hybrisadaptor.h +++ b/core/hybrisadaptor.h @@ -34,50 +34,68 @@ class HybrisAdaptor; +struct HybrisSensorState +{ + HybrisSensorState(); + ~HybrisSensorState(); + + int m_minDelay; + int m_maxDelay; + int m_delay; + int m_active; +}; + class HybrisManager : public QObject { Q_OBJECT public: - explicit HybrisManager(QObject *parent = 0); static HybrisManager *instance(); - virtual ~HybrisManager(); - - int handleForType(int sensorType); - int maxRange(int sensorType); - int minDelay(int sensorType); - int resolution(int sensorType); - - bool setDelay(int handle, int interval); - void startReader(HybrisAdaptor *adaptor); - void stopReader(HybrisAdaptor *adaptor); - - bool resumeReader(HybrisAdaptor *adaptor); - void standbyReader(HybrisAdaptor *adaptor); - - bool openSensors(); - bool closeSensors(); - - void registerAdaptor(HybrisAdaptor * adaptor); - void processSample(const sensors_event_t& data); + explicit HybrisManager(QObject *parent = 0); + virtual ~HybrisManager(); -protected: - // methods - void init(); - void closeAllSensors(); + /* - - - - - - - - - - - - - - - - - - - * + * android sensor hal functions + * - - - - - - - - - - - - - - - - - - - */ + + int halIndexForHandle(int handle) const; + int halIndexForType (int sensorType) const; + int halHandleForType (int sensorType) const; + float halGetMaxRange (int handle) const; + float halGetResolution (int handle) const; + int halGetMinDelay (int handle) const; + int halGetMaxDelay (int handle) const; + int halGetDelay (int handle) const; + bool halSetDelay (int handle, int delay_ms); + bool halGetActive (int handle) const; + bool halSetActive (int handle, bool active); + + /* - - - - - - - - - - - - - - - - - - - * + * HybrisManager <--> sensorfwd + * - - - - - - - - - - - - - - - - - - - */ + + void startReader (HybrisAdaptor *adaptor); + void stopReader (HybrisAdaptor *adaptor); + void registerAdaptor (HybrisAdaptor * adaptor); + void processSample (const sensors_event_t& data); +private: // fields - struct sensors_poll_device_t* device; - struct sensor_t const* sensorList; - struct sensors_module_t* module; - int sensorsCount; - QMap sensorMap; //type, index - QMap registeredAdaptors; //type, obj - pthread_t adaptorReaderTid; + bool m_initialized; + QMap m_registeredAdaptors; // type -> obj + struct sensors_module_t *m_halModule; + struct sensors_poll_device_t *m_halDevice; + int m_halSensorCount; + const struct sensor_t *m_halSensorArray; // [m_halSensorCount] + HybrisSensorState *m_halSensorState; // [m_halSensorCount] + QMap m_halIndexOfType; // type -> index + QMap m_halIndexOfHandle; // handle -> index + pthread_t m_halEventReaderTid; + friend class HybrisAdaptorReader; private: - static void *adaptorReaderThread(void *aptr); + static void *halEventReaderThread(void *aptr); }; class HybrisAdaptor : public DeviceAdaptor @@ -87,47 +105,44 @@ class HybrisAdaptor : public DeviceAdaptor virtual ~HybrisAdaptor(); virtual void init(); - bool addSensorType(int type); + virtual bool startAdaptor(); - bool isRunning() const; + bool isRunning() const; virtual void stopAdaptor(); + void evaluateSensor(); virtual bool startSensor(); virtual void stopSensor(); virtual bool standby(); - virtual bool resume(); - qreal maxRange; - qint32 minDelay; - qreal resolution; + virtual void sendInitialData(); friend class HybrisManager; - int sensorHandle; - int sensorType; - int cachedInterval; - - virtual void sendInitialData() {} protected: virtual void processSample(const sensors_event_t& data) = 0; + qreal minRange() const; + qreal maxRange() const; + qreal resolution() const; + + unsigned int minInterval() const; + unsigned int maxInterval() const; + virtual unsigned int interval() const; virtual bool setInterval(const unsigned int value, const int sessionId); virtual unsigned int evaluateIntervalRequests(int& sessionId) const; static bool writeToFile(const QByteArray& path, const QByteArray& content); private: - void stopReaderThread(); - bool startReaderThread(); - - QList sensorIds; - unsigned int interval_; - bool inStandbyMode_; - volatile bool running_; - bool shouldBeRunning_; + bool m_inStandbyMode; + volatile bool m_isRunning; + bool m_shouldBeRunning; + int m_sensorHandle; + int m_sensorType; }; #endif // HybrisAdaptor_H