blob: c9388b0012c872131dbad4a6349a5970026a7895 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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.
*/
#include <cstdint>
#include <cutils/properties.h>
#include <cutils/sockets.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/system_properties.h>
#include <unistd.h>
#include <algorithm>
#include "common/libs/fs/shared_select.h"
#include "common/libs/threads/thunkers.h"
#include "guest/hals/sensors/sensors_hal.h"
#include "guest/hals/sensors/vsoc_sensors.h"
#include "guest/hals/sensors/vsoc_sensors_message.h"
#include "guest/libs/remoter/remoter_framework_pkt.h"
using cvd::LockGuard;
using cvd::Mutex;
using cvd::time::Milliseconds;
using cvd::time::MonotonicTimePoint;
using cvd::time::Nanoseconds;
namespace cvd {
int GceSensors::total_sensor_count_ = -1;
SensorInfo* GceSensors::sensor_infos_ = NULL;
const int GceSensors::kInjectedEventWaitPeriods = 3;
const Nanoseconds GceSensors::kInjectedEventWaitTime =
Nanoseconds(Milliseconds(20));
GceSensors::GceSensors()
: sensors_poll_device_1(), deadline_change_(&sensor_state_lock_) {
if (total_sensor_count_ == -1) {
RegisterSensors();
}
// Create a pair of FDs that would be used to control the
// receiver thread.
if (control_sender_socket_->IsOpen() || control_receiver_socket_->IsOpen()) {
ALOGE("%s: Receiver control FDs are opened", __FUNCTION__);
}
if (!cvd::SharedFD::Pipe(&control_receiver_socket_,
&control_sender_socket_)) {
ALOGE("%s: Unable to create thread control FDs: %d -> %s", __FUNCTION__,
errno, strerror(errno));
}
// Create the correct number of holding buffers for this client.
sensor_states_.resize(total_sensor_count_);
int i;
for (i = 0; i < total_sensor_count_; i++) {
sensor_states_[i] = new SensorState(sensor_infos_[i]);
}
}
GceSensors::~GceSensors() {
int i;
for (i = 0; i < total_sensor_count_; i++) {
delete sensor_states_[i];
}
}
int GceSensors::GetSensorsList(struct sensors_module_t* /*module*/,
struct sensor_t const** list) {
*list = sensor_infos_;
return total_sensor_count_;
}
int GceSensors::SetOperationMode(unsigned int /* is_loopback_mode */) {
return -EINVAL;
}
int GceSensors::Open(const struct hw_module_t* module, const char* name,
struct hw_device_t** device) {
int status = -EINVAL;
if (!strcmp(name, SENSORS_HARDWARE_POLL)) {
// Create a new GceSensors object and set all the fields/functions
// to their default values.
GceSensors* rval = new GceSensors;
rval->common.tag = HARDWARE_DEVICE_TAG;
rval->common.version = VSOC_SENSOR_DEVICE_VERSION;
rval->common.module = (struct hw_module_t*)module;
rval->common.close = cvd::thunk<hw_device_t, &GceSensors::Close>;
rval->poll = cvd::thunk<sensors_poll_device_t, &GceSensors::Poll>;
rval->activate = cvd::thunk<sensors_poll_device_t, &GceSensors::Activate>;
rval->setDelay = cvd::thunk<sensors_poll_device_t, &GceSensors::SetDelay>;
rval->batch = cvd::thunk<sensors_poll_device_1, &GceSensors::Batch>;
rval->flush = cvd::thunk<sensors_poll_device_1, &GceSensors::Flush>;
rval->inject_sensor_data =
cvd::thunk<sensors_poll_device_1, &GceSensors::InjectSensorData>;
// Spawn a thread to listen for incoming data from the remoter.
int err = pthread_create(
&rval->receiver_thread_, NULL,
cvd::thunk<void, &GceSensors::Receiver>,
rval);
if (err) {
ALOGE("GceSensors::%s: Unable to start receiver thread (%s)",
__FUNCTION__, strerror(err));
}
*device = &rval->common;
status = 0;
}
return status;
}
int GceSensors::Close() {
// Make certain the receiver thread wakes up.
SensorControlMessage msg;
msg.message_type = THREAD_STOP;
SendControlMessage(msg);
pthread_join(receiver_thread_, NULL);
delete this;
return 0;
}
int GceSensors::Activate(int handle, int enabled) {
if (handle < 0 || handle >= total_sensor_count_) {
ALOGE("GceSensors::%s: Bad handle %d", __FUNCTION__, handle);
return -1;
}
{
LockGuard<Mutex> guard(sensor_state_lock_);
// Update the report deadline, if changed.
if (enabled && !sensor_states_[handle]->enabled_) {
sensor_states_[handle]->deadline_ =
MonotonicTimePoint::Now() + sensor_states_[handle]->sampling_period_;
} else if (!enabled && sensor_states_[handle]->enabled_) {
sensor_states_[handle]->deadline_ = SensorState::kInfinity;
}
sensor_states_[handle]->enabled_ = enabled;
UpdateDeadline();
}
D("sensor_activate(): handle %d, enabled %d", handle, enabled);
if (!UpdateRemoterState(handle)) {
ALOGE("Failed to notify remoter about new sensor enable/disable.");
}
return 0;
}
int GceSensors::SetDelay(int handle, int64_t sampling_period_ns) {
if (handle < 0 || handle >= total_sensor_count_) {
ALOGE("GceSensors::%s: Bad handle %d", __FUNCTION__, handle);
return -1;
}
int64_t min_delay_ns = sensor_infos_[handle].minDelay * 1000;
if (sampling_period_ns < min_delay_ns) {
sampling_period_ns = min_delay_ns;
}
{
LockGuard<Mutex> guard(sensor_state_lock_);
sensor_states_[handle]->deadline_ -=
sensor_states_[handle]->sampling_period_;
sensor_states_[handle]->sampling_period_ = Nanoseconds(sampling_period_ns);
sensor_states_[handle]->deadline_ +=
sensor_states_[handle]->sampling_period_;
// If our sampling period has decreased, our deadline
// could have already passed. If so, report immediately, but not in the
// past.
MonotonicTimePoint now = MonotonicTimePoint::Now();
if (sensor_states_[handle]->deadline_ < now) {
sensor_states_[handle]->deadline_ = now;
}
UpdateDeadline();
}
D("sensor_set_delay(): handle %d, delay (ms) %" PRId64, handle,
Milliseconds(Nanoseconds(sampling_period_ns)).count());
if (!UpdateRemoterState(handle)) {
ALOGE("Failed to notify remoter about new sensor delay.");
}
return 0;
}
int GceSensors::Poll(sensors_event_t* data, int count_unsafe) {
if (count_unsafe <= 0) {
ALOGE("Framework polled with bad count (%d)", count_unsafe);
return -1;
}
size_t count = size_t(count_unsafe);
// Poll will block until 1 of 2 things happens:
// 1. The next deadline for some active sensor
// occurs.
// 2. The next deadline changes (either because
// a sensor was activated/deactivated or its
// delay changed).
// In both cases, any sensors whose report deadlines
// have passed will report their data (or mock data),
// and poll will either return (if at least one deadline
// has passed), or repeat by blocking until the next deadline.
LockGuard<Mutex> guard(sensor_state_lock_);
current_deadline_ = UpdateDeadline();
// Sleep until we have something to report
while (!fifo_.size()) {
deadline_change_.WaitUntil(current_deadline_);
current_deadline_ = UpdateDeadline();
}
// Copy the events from the buffer
int num_copied = std::min(fifo_.size(), count);
FifoType::iterator first_uncopied = fifo_.begin() + num_copied;
std::copy(fifo_.begin(), first_uncopied, data);
fifo_.erase(fifo_.begin(), first_uncopied);
D("Reported %d sensor events. First: %d %f %f %f", num_copied, data->sensor,
data->data[0], data->data[1], data->data[2]);
return num_copied;
}
void *GceSensors::Receiver() {
// Initialize the server.
sensor_listener_socket_ = cvd::SharedFD::SocketSeqPacketServer(
gce_sensors_message::kSensorsHALSocketName, 0777);
if (!sensor_listener_socket_->IsOpen()) {
ALOGE("GceSensors::%s: Could not listen for sensor connections. (%s).",
__FUNCTION__, sensor_listener_socket_->StrError());
return NULL;
}
D("GceSensors::%s: Listening for sensor connections at %s", __FUNCTION__,
gce_sensors_message::kSensorsHALSocketName);
// Announce that we are ready for the remoter to connect.
if (!NotifyRemoter()) {
ALOGI("Failed to notify remoter that HAL is ready.");
} else {
ALOGI("Notified remoter that HAL is ready.");
}
typedef std::vector<cvd::SharedFD> FDVec;
FDVec connected;
// Listen for incoming sensor data and control messages
// from the HAL.
while (true) {
cvd::SharedFDSet fds;
for (FDVec::iterator it = connected.begin(); it != connected.end(); ++it) {
fds.Set(*it);
}
fds.Set(control_receiver_socket_);
// fds.Set(sensor_listener_socket_);
int res = cvd::Select(&fds, NULL, NULL, NULL);
if (res == -1) {
ALOGE("%s: select returned %d and failed %d -> %s", __FUNCTION__, res,
errno, strerror(errno));
break;
} else if (res == 0) {
ALOGE("%s: select timed out", __FUNCTION__);
break;
} else if (fds.IsSet(sensor_listener_socket_)) {
connected.push_back(cvd::SharedFD::Accept(*sensor_listener_socket_));
ALOGI("GceSensors::%s: new client connected", __FUNCTION__);
} else if (fds.IsSet(control_receiver_socket_)) {
// We received a control message.
SensorControlMessage msg;
int res =
control_receiver_socket_->Read(&msg, sizeof(SensorControlMessage));
if (res == -1) {
ALOGE("GceSensors::%s: Failed to receive control message.",
__FUNCTION__);
} else if (res == 0) {
ALOGE("GceSensors::%s: Control connection closed.", __FUNCTION__);
}
if (msg.message_type == SENSOR_STATE_UPDATE) {
// Forward the update to the remoter.
remoter_request_packet packet;
remoter_request_packet_init(&packet, kRemoterSensorState, 0);
{
LockGuard<Mutex> guard(sensor_state_lock_);
packet.params.sensor_state_params.type =
sensor_infos_[msg.sensor_handle].type;
packet.params.sensor_state_params.enabled =
sensor_states_[msg.sensor_handle]->enabled_;
packet.params.sensor_state_params.delay_ns =
sensor_states_[msg.sensor_handle]->sampling_period_.count();
packet.params.sensor_state_params.handle = msg.sensor_handle;
}
struct msghdr msg;
iovec msg_iov[1];
msg_iov[0].iov_base = &packet;
msg_iov[0].iov_len = sizeof(remoter_request_packet);
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = msg_iov;
msg.msg_iovlen = arraysize(msg_iov);
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
for (FDVec::iterator it = connected.begin(); it != connected.end();
++it) {
cvd::SharedFD &fd = *it;
if (fd->SendMsg(&msg, 0) == -1) {
ALOGE("GceSensors::%s. Could not send sensor state (%s).",
__FUNCTION__, fd->StrError());
}
}
}
if (msg.message_type == THREAD_STOP) {
D("Received terminate control message.");
return NULL;
}
} else {
for (FDVec::iterator it = connected.begin(); it != connected.end();
++it) {
cvd::SharedFD &fd = *it;
if (fds.IsSet(fd)) {
// We received a sensor update from remoter.
sensors_event_t event;
struct msghdr msg;
iovec msg_iov[1];
msg_iov[0].iov_base = &event;
msg_iov[0].iov_len = sizeof(event);
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = msg_iov;
msg.msg_iovlen = arraysize(msg_iov);
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
int res = fd->RecvMsg(&msg, 0);
if (res <= 0) {
if (res == 0) {
ALOGE("GceSensors::%s: Sensors HAL connection closed.",
__FUNCTION__);
} else {
ALOGE("GceSensors::%s: Failed to receive sensor message",
__FUNCTION__);
}
connected.erase(std::find(connected.begin(), connected.end(), fd));
break;
}
// We received an event from the remoter.
if (event.sensor < 0 || event.sensor >= total_sensor_count_) {
ALOGE("Remoter sent us an invalid sensor event! (handle %d)",
event.sensor);
connected.erase(std::find(connected.begin(), connected.end(), fd));
break;
}
D("Received sensor event: %d %f %f %f", event.sensor, event.data[0],
event.data[1], event.data[2]);
{
LockGuard<Mutex> guard(sensor_state_lock_);
// Increase the delay so that the HAL knows
// it shouldn't report on its own for a while.
SensorState *holding_buffer = sensor_states_[event.sensor];
int wait_periods =
std::max(kInjectedEventWaitPeriods,
(int)(kInjectedEventWaitTime.count() /
holding_buffer->sampling_period_.count()));
holding_buffer->deadline_ =
MonotonicTimePoint::Now() +
holding_buffer->sampling_period_ * wait_periods;
holding_buffer->event_.data[0] = event.data[0];
holding_buffer->event_.data[1] = event.data[1];
holding_buffer->event_.data[2] = event.data[2];
// Signal the HAL to report the newly arrived event.
fifo_.push_back(event);
deadline_change_.NotifyOne();
}
}
}
}
}
return NULL;
}
bool GceSensors::NotifyRemoter() {
remoter_request_packet packet;
remoter_request_packet_init(&packet, kRemoterHALReady, 0);
packet.send_response = 0;
strncpy(packet.params.hal_ready_params.unix_socket,
gce_sensors_message::kSensorsHALSocketName,
sizeof(packet.params.hal_ready_params.unix_socket));
AutoCloseFileDescriptor remoter_socket(remoter_connect());
if (remoter_socket.IsError()) {
D("GceSensors::%s: Could not connect to remoter to notify ready (%s).",
__FUNCTION__, strerror(errno));
return false;
}
int err =
remoter_do_single_request_with_socket(remoter_socket, &packet, NULL);
if (err == -1) {
D("GceSensors::%s: Notify remoter ready: Failed after connect (%s).",
__FUNCTION__, strerror(errno));
return false;
}
D("GceSensors::%s: Notify remoter ready Succeeded.", __FUNCTION__);
return true;
}
static bool CompareTimestamps(const sensors_event_t& a,
const sensors_event_t& b) {
return a.timestamp < b.timestamp;
}
MonotonicTimePoint GceSensors::UpdateDeadline() {
// Get the minimum of all the current deadlines.
MonotonicTimePoint now = MonotonicTimePoint::Now();
MonotonicTimePoint min = SensorState::kInfinity;
int i = 0;
bool sort_fifo = false;
for (i = 0; i < total_sensor_count_; i++) {
SensorState* holding_buffer = sensor_states_[i];
// Ignore disabled sensors.
if (!holding_buffer->enabled_) {
continue;
}
while (holding_buffer->deadline_ < now) {
sensors_event_t data = holding_buffer->event_;
data.timestamp = holding_buffer->deadline_.SinceEpoch().count();
fifo_.push_back(data);
holding_buffer->deadline_ += holding_buffer->sampling_period_;
sort_fifo = true;
}
// Now check if we should update the wake time based on the next event
// from this sensor.
if (sensor_states_[i]->deadline_ < min) {
min = sensor_states_[i]->deadline_;
}
}
// We added one or more sensor readings, so do a sort.
// This is likely to be cheaper than a traditional priority queue because
// a priority queue would try to keep its state correct for each addition.
if (sort_fifo) {
std::sort(fifo_.begin(), fifo_.end(), CompareTimestamps);
}
// If we added events or the deadline is lower notify the thread in Poll().
// If the deadline went up, don't do anything.
if (fifo_.size() || (min < current_deadline_)) {
deadline_change_.NotifyOne();
}
return min;
}
bool GceSensors::UpdateRemoterState(int handle) {
SensorControlMessage msg;
msg.message_type = SENSOR_STATE_UPDATE;
msg.sensor_handle = handle;
return SendControlMessage(msg);
}
bool GceSensors::SendControlMessage(SensorControlMessage msg) {
if (!control_sender_socket_->IsOpen()) {
ALOGE("%s: Can't send control message %d, control socket not open.",
__FUNCTION__, msg.message_type);
return false;
}
if (control_sender_socket_->Write(&msg, sizeof(SensorControlMessage)) == -1) {
ALOGE("GceSensors::%s. Could not send control message %d (%s).",
__FUNCTION__, msg.message_type, control_sender_socket_->StrError());
return false;
}
return true;
}
int GceSensors::RegisterSensors() {
if (total_sensor_count_ != -1) {
return -1;
}
total_sensor_count_ = 9;
sensor_infos_ = new SensorInfo[total_sensor_count_];
sensor_infos_[sensors_constants::kAccelerometerHandle] =
AccelerometerSensor();
sensor_infos_[sensors_constants::kGyroscopeHandle] = GyroscopeSensor();
sensor_infos_[sensors_constants::kLightHandle] = LightSensor();
sensor_infos_[sensors_constants::kMagneticFieldHandle] =
MagneticFieldSensor();
sensor_infos_[sensors_constants::kPressureHandle] = PressureSensor();
sensor_infos_[sensors_constants::kProximityHandle] = ProximitySensor();
sensor_infos_[sensors_constants::kAmbientTempHandle] = AmbientTempSensor();
sensor_infos_[sensors_constants::kDeviceTempHandle] = DeviceTempSensor();
sensor_infos_[sensors_constants::kRelativeHumidityHandle] =
RelativeHumiditySensor();
int i;
for (i = 0; i < total_sensor_count_; i++) {
D("Found sensor %s with handle %d", sensor_infos_[i].name,
sensor_infos_[i].handle);
}
return total_sensor_count_;
}
} // namespace cvd