blob: 59b433ff26333736bb4425973b0fbc23a8108a81 [file] [log] [blame]
#include "sensor_hal_thread.h"
#include <cutils/log.h>
#include <dvr/performance_client_api.h>
namespace android {
namespace dvr {
SensorHalThread::SensorHalThread(bool* out_success)
: shutting_down_(false),
paused_(false),
sensor_module_(nullptr),
sensor_device_(nullptr),
sensor_list_(nullptr) {
// Assume failure; we will change this to true on success.
*out_success = false;
// TODO(segal): module & device should be singletons.
int32_t err = hw_get_module_by_class(SENSORS_HARDWARE_MODULE_ID, "platform",
(hw_module_t const**)&sensor_module_);
if (err) {
ALOGE("couldn't load %s module (%s)", SENSORS_HARDWARE_MODULE_ID,
strerror(-err));
return;
}
err = sensors_open_1(&sensor_module_->common, &sensor_device_);
if (err) {
ALOGE("couldn't open device for module %s (%s)", SENSORS_HARDWARE_MODULE_ID,
strerror(-err));
return;
}
const int sensor_count =
sensor_module_->get_sensors_list(sensor_module_, &sensor_list_);
// Deactivate all of the sensors initially.
sensor_user_count_.resize(sensor_count, 0);
for (int i = 0; i < sensor_count; ++i) {
err = sensor_device_->activate(
reinterpret_cast<struct sensors_poll_device_t*>(sensor_device_),
sensor_list_[i].handle, 0);
if (err) {
ALOGE("failed to deactivate sensor %d (%s)", i, strerror(-err));
return;
}
}
// At this point, we've successfully initialized everything.
*out_success = true;
}
SensorHalThread::~SensorHalThread() {
{
std::unique_lock<std::mutex> lock(mutex_);
shutting_down_ = true;
condition_.notify_one();
}
// Implicitly joins *thread_ if it's running.
}
void SensorHalThread::StartPolling(const EventConsumer& consumer) {
if (thread_) {
ALOGE("SensorHalThread::Start() called but thread is already running!");
return;
}
thread_.reset(new std::thread([this, consumer] {
const int priority_error = dvrSetSchedulerClass(0, "sensors:high");
LOG_ALWAYS_FATAL_IF(
priority_error < 0,
"SensorHalTread::StartPolling: Failed to set scheduler class: %s",
strerror(-priority_error));
for (;;) {
for (;;) {
std::unique_lock<std::mutex> lock(mutex_);
if (shutting_down_)
return;
if (!paused_)
break;
condition_.wait(lock);
}
const int kMaxEvents = 100;
sensors_event_t events[kMaxEvents];
ssize_t event_count = 0;
do {
if (sensor_device_) {
event_count = sensor_device_->poll(
reinterpret_cast<struct sensors_poll_device_t*>(sensor_device_),
events, kMaxEvents);
} else {
// When there is no sensor_device_, we still call the consumer at
// regular intervals in case mock poses are in use. Note that this
// will never be the case for production devices, but this helps
// during bringup.
usleep(5000);
}
} while (event_count == -EINTR);
if (event_count == kMaxEvents)
ALOGI("max events (%d) reached", kMaxEvents);
if (event_count >= 0) {
consumer(events, events + event_count);
} else {
ALOGE(
"SensorHalThread::StartPolling: Error while polling sensor: %s "
"(%zd)",
strerror(-event_count), -event_count);
}
}
}));
}
void SensorHalThread::SetPaused(bool is_paused) {
std::unique_lock<std::mutex> lock(mutex_);
paused_ = is_paused;
condition_.notify_one();
}
void SensorHalThread::StartUsingSensor(const int sensor_index) {
if (sensor_index < 0 || sensor_index >= GetSensorCount()) {
ALOGE("StartUsingSensor(): sensor index %d out of range [0, %d)",
sensor_index, GetSensorCount());
return;
}
std::lock_guard<std::mutex> guard(user_count_mutex_);
if (sensor_user_count_[sensor_index]++ == 0) {
sensor_device_->activate(
reinterpret_cast<struct sensors_poll_device_t*>(sensor_device_),
sensor_list_[sensor_index].handle, 1);
sensor_device_->setDelay(
reinterpret_cast<struct sensors_poll_device_t*>(sensor_device_),
sensor_list_[sensor_index].handle, 0);
}
}
void SensorHalThread::StopUsingSensor(const int sensor_index) {
if (sensor_index < 0 || sensor_index >= GetSensorCount()) {
ALOGE("StopUsingSensor(): sensor index %d out of range [0, %d)",
sensor_index, GetSensorCount());
return;
}
std::lock_guard<std::mutex> guard(user_count_mutex_);
if (--sensor_user_count_[sensor_index] == 0) {
sensor_device_->activate(
reinterpret_cast<struct sensors_poll_device_t*>(sensor_device_),
sensor_list_[sensor_index].handle, 0);
}
}
} // namespace dvr
} // namespace android