typedef void (*sensor_events_cb_t)(sensor_t sensor, unsigned int event_type, sensor_data_t* events[], int events_count, void *user_data);
typedef void (*sensorhub_cb_t)(sensor_t sensor, unsigned int event_type, sensorhub_data_t *data, void *user_data);
typedef void (*sensor_accuracy_changed_cb_t) (sensor_t sensor, unsigned long long timestamp, int accuracy, void *user_data);
-typedef void (*sensor_attribute_int_changed_cb_t)(sensor_t sensor, int attribute, int value, void *data);
-typedef void (*sensor_attribute_str_changed_cb_t)(sensor_t sensor, int attribute, const char *value, int len, void *data);
+typedef void (*sensor_attribute_int_changed_cb_t)(sensor_t sensor, int attribute, int value, void *user_data);
+typedef void (*sensor_attribute_str_changed_cb_t)(sensor_t sensor, int attribute, const char *value, int len, void *user_data);
/**
* @brief Get the list of available sensors of a certain type, use ALL_SENSOR to get all the sensors.
*/
bool sensord_unregister_accuracy_cb(int handle);
+/**
+ * @brief Register a callback with a connected sensor. This callback will be called when attributes of a sensor has changed.
+ *
+ * @param[in] handle a handle represensting a connected sensor.
+ * @param[in] cb a callback which is called when he attributes of a sensor has changed.
+ * @param[in] user_data the callback is called with user_data
+ * @return true on success, otherwise false.
+ */
bool sensord_register_attribute_int_changed_cb(int handle, sensor_attribute_int_changed_cb_t cb, void *user_data);
+/**
+ * @brief Unregister a callback with a connected sensor. After unregistering, sensor_attribute_int_changed_cb will not be called.
+ *
+ * @param[in] handle a handle represensting a connected sensor.
+ * @return true on success, otherwise false.
+ */
bool sensord_unregister_attribute_int_changed_cb(int handle);
+/**
+ * @brief Register a callback with a connected sensor. This callback will be called when attributes of a sensor has changed.
+ *
+ * @param[in] handle a handle represensting a connected sensor.
+ * @param[in] cb a callback which is called when he attributes of a sensor has changed.
+ * @param[in] user_data the callback is called with user_data
+ * @return true on success, otherwise false.
+ */
bool sensord_register_attribute_str_changed_cb(int handle, sensor_attribute_str_changed_cb_t cb, void *user_data);
+/**
+ * @brief Unregister a callback with a connected sensor. After unregistering, sensor_attribute_str_changed_cb will not be called.
+ *
+ * @param[in] handle a handle represensting a connected sensor.
+ * @return true on success, otherwise false.
+ */
bool sensord_unregister_attribute_str_changed_cb(int handle);
+
/**
* @brief Start listening events with a connected sensor.
*
#include <regex>
#include <thread>
#include <cmutex.h>
+#include <command_types.h>
#include "sensor_reader.h"
return FALSE;
}
-class sensor_listener_handler : public ipc::channel_handler
+static gboolean sensor_attribute_int_changed_callback_dispatcher(gpointer data)
+{
+ callback_info_s *info = (callback_info_s *)data;
+
+ AUTOLOCK(lock);
+
+ if (info->cb && info->sensor && listeners.find(info->listener_id) != listeners.end()) {
+ cmd_listener_attr_int_t *d = (cmd_listener_attr_int_t *)info->data;
+ ((sensor_attribute_int_changed_cb_t)info->cb)(info->sensor, d->attribute, d->value, info->user_data);
+ }
+
+ delete [] info->data;
+ delete info;
+ return FALSE;
+}
+
+static gboolean sensor_attribute_str_changed_callback_dispatcher(gpointer data)
+{
+ callback_info_s *info = (callback_info_s *)data;
+
+ AUTOLOCK(lock);
+
+ if (info->cb && info->sensor && listeners.find(info->listener_id) != listeners.end()) {
+ cmd_listener_attr_str_t *d = (cmd_listener_attr_str_t *)info->data;
+ ((sensor_attribute_str_changed_cb_t)info->cb)(info->sensor, d->attribute, d->value, d->len, info->user_data);
+ }
+
+ delete [] info->data;
+ delete info;
+ return FALSE;
+}
+
+class sensor_listener_channel_handler : public ipc::channel_handler
{
public:
- sensor_listener_handler(int id, sensor_t sensor, void* cb, void *user_data, callback_dispatcher_t dispatcher)
+ sensor_listener_channel_handler(int id, sensor_t sensor, void* cb, void *user_data, callback_dispatcher_t dispatcher)
: m_listener_id(id)
, m_sensor(reinterpret_cast<sensor_info *>(sensor))
, m_cb(cb)
sensor::sensor_listener *listener;
int prev_interval;
int prev_max_batch_latency;
- sensor_listener_handler *handler;
+ sensor_listener_channel_handler *handler;
AUTOLOCK(lock);
}
if (is_events_callback) {
- handler = new(std::nothrow)sensor_listener_handler(handle, listener->get_sensor(), (void *)cb, user_data, sensor_events_callback_dispatcher);
+ handler = new(std::nothrow)sensor_listener_channel_handler(handle, listener->get_sensor(), (void *)cb, user_data, sensor_events_callback_dispatcher);
} else {
- handler = new(std::nothrow)sensor_listener_handler(handle, listener->get_sensor(), (void *)cb, user_data, sensor_event_callback_dispatcher);
+ handler = new(std::nothrow)sensor_listener_channel_handler(handle, listener->get_sensor(), (void *)cb, user_data, sensor_event_callback_dispatcher);
}
if (!handler) {
API bool sensord_register_accuracy_cb(int handle, sensor_accuracy_changed_cb_t cb, void *user_data)
{
sensor::sensor_listener *listener;
- sensor_listener_handler *handler;
+ sensor_listener_channel_handler *handler;
AUTOLOCK(lock);
listener = it->second;
- handler = new(std::nothrow) sensor_listener_handler(handle, listener->get_sensor(), (void *)cb, user_data, sensor_accuracy_changed_callback_dispatcher);
+ handler = new(std::nothrow) sensor_listener_channel_handler(handle, listener->get_sensor(), (void *)cb, user_data, sensor_accuracy_changed_callback_dispatcher);
retvm_if(!handler, false, "Failed to allocate memory");
listener->set_accuracy_handler(handler);
API bool sensord_register_attribute_int_changed_cb(int handle, sensor_attribute_int_changed_cb_t cb, void *user_data)
{
- // TODO
- return false;
+ sensor::sensor_listener *listener;
+ sensor_listener_channel_handler *handler;
+
+ AUTOLOCK(lock);
+
+ auto it = listeners.find(handle);
+ retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle);
+
+ listener = it->second;
+
+ handler = new(std::nothrow) sensor_listener_channel_handler(handle, listener->get_sensor(), (void *)cb, user_data, sensor_attribute_int_changed_callback_dispatcher);
+ retvm_if(!handler, false, "Failed to allocate memory");
+
+ listener->set_attribute_int_changed_handler(handler);
+
+ return true;
}
API bool sensord_unregister_attribute_int_changed_cb(int handle)
{
- // TODO
- return false;
+ sensor::sensor_listener *listener;
+
+ AUTOLOCK(lock);
+
+ auto it = listeners.find(handle);
+ retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle);
+
+ listener = it->second;
+
+ listener->unset_attribute_int_changed_handler();
+
+ return true;
}
API bool sensord_register_attribute_str_changed_cb(int handle, sensor_attribute_str_changed_cb_t cb, void *user_data)
{
- // TODO
- return false;
+ sensor::sensor_listener *listener;
+ sensor_listener_channel_handler *handler;
+
+ AUTOLOCK(lock);
+
+ auto it = listeners.find(handle);
+ retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle);
+
+ listener = it->second;
+
+ handler = new(std::nothrow) sensor_listener_channel_handler(handle, listener->get_sensor(), (void *)cb, user_data, sensor_attribute_str_changed_callback_dispatcher);
+ retvm_if(!handler, false, "Failed to allocate memory");
+
+ listener->set_attribute_str_changed_handler(handler);
+
+ return true;
}
API bool sensord_unregister_attribute_str_changed_cb(int handle)
{
- // TODO
- return false;
+ sensor::sensor_listener *listener;
+
+ AUTOLOCK(lock);
+
+ auto it = listeners.find(handle);
+ retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle);
+
+ listener = it->second;
+
+ listener->unset_attribute_str_changed_handler();
+
+ return true;
}
API bool sensord_start(int handle, int option)
listener_handler(sensor_listener *listener)
: m_listener(listener)
{}
+
void connected(ipc::channel *ch) {}
void disconnected(ipc::channel *ch)
{
if (m_listener->get_accuracy_handler())
m_listener->get_accuracy_handler()->read(ch, msg);
break;
+ case CMD_LISTENER_ATTR_INT:
+ if (m_listener->get_attribute_int_changed_handler())
+ m_listener->get_attribute_int_changed_handler()->read(ch, msg);
+ break;
+ case CMD_LISTENER_ATTR_STR:
+ if (m_listener->get_attribute_str_changed_handler())
+ m_listener->get_attribute_str_changed_handler()->read(ch, msg);
+ break;
+ default:
+ _W("Invalid command message");
}
}
, m_handler(NULL)
, m_evt_handler(NULL)
, m_acc_handler(NULL)
+, m_attr_int_changed_handler(NULL)
+, m_attr_str_changed_handler(NULL)
, m_connected(false)
, m_started(false)
{
, m_handler(NULL)
, m_evt_handler(NULL)
, m_acc_handler(NULL)
+, m_attr_int_changed_handler(NULL)
+, m_attr_str_changed_handler(NULL)
, m_loop(loop)
, m_connected(false)
, m_started(false)
delete m_client;
m_client = NULL;
+ delete m_evt_handler;
+ m_evt_handler = NULL;
+
+ delete m_acc_handler;
+ m_acc_handler = NULL;
+
+ delete m_attr_int_changed_handler;
+ m_attr_int_changed_handler = NULL;
+
+ delete m_attr_str_changed_handler;
+ m_attr_str_changed_handler = NULL;
+
m_attributes.clear();
_D("Deinitialized..");
}
void sensor_listener::set_event_handler(ipc::channel_handler *handler)
{
AUTOLOCK(lock);
-
+ if (m_evt_handler) {
+ delete m_evt_handler;
+ }
m_evt_handler = handler;
}
ipc::channel_handler *sensor_listener::get_accuracy_handler(void)
{
+ AUTOLOCK(lock);
return m_acc_handler;
}
void sensor_listener::set_accuracy_handler(ipc::channel_handler *handler)
{
+ AUTOLOCK(lock);
+ if (m_acc_handler) {
+ delete m_acc_handler;
+ }
m_acc_handler = handler;
}
void sensor_listener::unset_accuracy_handler(void)
{
+ AUTOLOCK(lock);
delete m_acc_handler;
m_acc_handler = NULL;
}
+ipc::channel_handler *sensor_listener::get_attribute_int_changed_handler(void)
+{
+ AUTOLOCK(lock);
+ return m_attr_int_changed_handler;
+}
+
+void sensor_listener::set_attribute_int_changed_handler(ipc::channel_handler *handler)
+{
+ AUTOLOCK(lock);
+ if (m_attr_int_changed_handler) {
+ delete m_attr_int_changed_handler;
+ }
+ m_attr_int_changed_handler = handler;
+}
+
+void sensor_listener::unset_attribute_int_changed_handler(void)
+{
+ AUTOLOCK(lock);
+ delete m_attr_int_changed_handler;
+ m_attr_int_changed_handler = NULL;
+}
+
+ipc::channel_handler *sensor_listener::get_attribute_str_changed_handler(void)
+{
+ AUTOLOCK(lock);
+ return m_attr_str_changed_handler;
+}
+
+void sensor_listener::set_attribute_str_changed_handler(ipc::channel_handler *handler)
+{
+ AUTOLOCK(lock);
+ if (m_attr_str_changed_handler) {
+ delete m_attr_str_changed_handler;
+ }
+ m_attr_str_changed_handler = handler;
+}
+
+void sensor_listener::unset_attribute_str_changed_handler(void)
+{
+ AUTOLOCK(lock);
+ delete m_attr_str_changed_handler;
+ m_attr_str_changed_handler = NULL;
+}
+
int sensor_listener::start(void)
{
ipc::message msg;
size = sizeof(cmd_listener_attr_str_t) + len;
- buf = (cmd_listener_attr_str_t *) malloc(sizeof(char) * size);
+ buf = (cmd_listener_attr_str_t *) new(std::nothrow) char[size];
retvm_if(!buf, -ENOMEM, "Failed to allocate memory");
msg.set_type(CMD_LISTENER_ATTR_STR);
/* Message memory is released automatically after sending message,
so it doesn't need to free memory */
+ delete [] buf;
+
if (reply.header()->err < 0)
return reply.header()->err;
ipc::channel_handler *get_event_handler(void);
ipc::channel_handler *get_accuracy_handler(void);
+ ipc::channel_handler *get_attribute_int_changed_handler(void);
+ ipc::channel_handler *get_attribute_str_changed_handler(void);
/* TODO: modify the listener so that it can register multiple handlers(1:n) */
void set_event_handler(ipc::channel_handler *handler);
void set_accuracy_handler(ipc::channel_handler *handler);
+ void set_attribute_int_changed_handler(ipc::channel_handler *handler);
+ void set_attribute_str_changed_handler(ipc::channel_handler *handler);
void unset_event_handler(void);
void unset_accuracy_handler(void);
+ void unset_attribute_int_changed_handler(void);
+ void unset_attribute_str_changed_handler(void);
int start(void);
int stop(void);
ipc::channel_handler *m_handler;
ipc::channel_handler *m_evt_handler;
ipc::channel_handler *m_acc_handler;
+ ipc::channel_handler *m_attr_int_changed_handler;
+ ipc::channel_handler *m_attr_str_changed_handler;
+
ipc::event_loop *m_loop;
std::atomic<bool> m_connected;
std::atomic<bool> m_started;
static gboolean change_attribute_str(gpointer gdata)
{
int *handle = reinterpret_cast<int *>(gdata);
- int len = strlen(attribute_value_str);
+ int len = strlen(attribute_value_str) + 1;
sensord_set_attribute_str(*handle, attribute, attribute_value_str, len);
_N("[ SET ATTRIBUTE STR ] attribute %d, value : %s, len : %d\n", attribute, attribute_value_str, len);
/* subscriber */
int update(const char *uri, ipc::message *msg);
+ int on_attribute_changed(ipc::message *msg)
+ {
+ // Do nothing
+ return OP_SUCCESS;
+ }
/* sensor interface */
const sensor_info &get_sensor_info(void);
#include <sensor_log.h>
#include <sensor_utils.h>
#include <sensor_types_private.h>
+#include <command_types.h>
using namespace sensor;
return 0;
}
+bool sensor_handler::notify_attribute_changed(int attribute, int value)
+{
+ if (observer_count() == 0)
+ return OP_ERROR;
+
+ cmd_listener_attr_int_t buf;
+ buf.attribute = attribute;
+ buf.value = value;
+
+ ipc::message *msg;
+ msg = new(std::nothrow) ipc::message();
+ retvm_if(!msg, OP_ERROR, "Failed to allocate memory");
+
+ msg->set_type(CMD_LISTENER_ATTR_INT);
+ msg->enclose((char *)&buf, sizeof(buf));
+
+ for (auto it = m_observers.begin(); it != m_observers.end(); ++it)
+ (*it)->on_attribute_changed(msg);
+
+ if (msg->ref_count() == 0)
+ msg->unref();
+
+ return OP_SUCCESS;
+}
+
+bool sensor_handler::notify_attribute_changed(int attribute, const char *value, int len)
+{
+ if (observer_count() == 0)
+ return OP_ERROR;
+
+ cmd_listener_attr_str_t *buf;
+ size_t size;
+ size = sizeof(cmd_listener_attr_str_t) + len;
+ buf = (cmd_listener_attr_str_t *) new(std::nothrow) char[size];
+ retvm_if(!buf, -ENOMEM, "Failed to allocate memory");
+
+ ipc::message *msg;
+ msg = new(std::nothrow) ipc::message();
+ retvm_if(!msg, OP_ERROR, "Failed to allocate memory");
+
+ buf->attribute = attribute;
+ memcpy(buf->value, value, len);
+ buf->len = len;
+
+ msg->set_type(CMD_LISTENER_ATTR_STR);
+ msg->enclose((char *)buf, size);
+
+ for (auto it = m_observers.begin(); it != m_observers.end(); ++it)
+ (*it)->on_attribute_changed(msg);
+
+ if (msg->ref_count() == 0)
+ msg->unref();
+
+ delete[] buf;
+
+ return OP_SUCCESS;
+}
+
int sensor_handler::delete_batch_latency(sensor_observer *ob)
{
return 0;
void set_cache(sensor_data_t *data, int size);
int get_cache(sensor_data_t **data, int *len);
+ bool notify_attribute_changed(int attribute, int value);
+ bool notify_attribute_changed(int attribute, const char *value, int len);
protected:
sensor_info m_info;
return OP_CONTINUE;
}
+int sensor_listener_proxy::on_attribute_changed(ipc::message *msg)
+{
+ retv_if(!m_ch || !m_ch->is_connected(), OP_CONTINUE);
+
+ m_ch->send(msg);
+ return OP_CONTINUE;
+}
+
void sensor_listener_proxy::update_event(ipc::message *msg)
{
/* TODO: check axis orientation */
if (!(value & m_pause_policy))
start(true);
}
+
+bool sensor_listener_proxy::notify_attribute_changed(int attribute, int value)
+{
+ sensor_handler *sensor = m_manager->get_sensor(m_uri);
+ retv_if(!sensor, -EINVAL);
+
+ return sensor->notify_attribute_changed(attribute, value);
+}
+
+bool sensor_listener_proxy::notify_attribute_changed(int attribute, const char *value, int len)
+{
+ sensor_handler *sensor = m_manager->get_sensor(m_uri);
+ retv_if(!sensor, -EINVAL);
+
+ return sensor->notify_attribute_changed(attribute, value, len);
+}
\ No newline at end of file
/* sensor observer */
int update(const char *uri, ipc::message *msg);
+ int on_attribute_changed(ipc::message *msg);
int start(bool policy = false);
int stop(bool policy = false);
/* sensor_policy_listener interface */
void on_policy_changed(int policy, int value);
+ bool notify_attribute_changed(int attribute, int value);
+ bool notify_attribute_changed(int attribute, const char *value, int len);
private:
void update_event(ipc::message *msg);
/* for performance, use message */
virtual int update(const char *uri, ipc::message *msg) = 0;
+ virtual int on_attribute_changed(ipc::message *msg) = 0;
};
}
-EACCES, "Permission denied[%d, %s]",
id, m_listeners[id]->get_required_privileges().c_str());
+ bool need_notify = false;
+
switch (buf.attribute) {
case SENSORD_ATTRIBUTE_INTERVAL:
ret = m_listeners[id]->set_interval(buf.value); break;
case SENSORD_ATTRIBUTE_AXIS_ORIENTATION:
default:
ret = m_listeners[id]->set_attribute(buf.attribute, buf.value);
+ if (ret == OP_SUCCESS) {
+ need_notify = true;
+ }
}
/* TODO : check return value */
if (ret < 0)
_D("Return : %d", ret);
- return send_reply(ch, OP_SUCCESS);
+ ret = send_reply(ch, OP_SUCCESS);
+
+ if (need_notify) {
+ m_listeners[id]->notify_attribute_changed(buf.attribute, buf.value);
+ }
+
+ return ret;
}
int server_channel_handler::listener_attr_str(channel *ch, message &msg)
return ret;
}
+ ret = send_reply(ch, OP_SUCCESS);
+ m_listeners[id]->notify_attribute_changed(buf->attribute, buf->value, buf->len);
+
delete [] buf;
- return send_reply(ch, OP_SUCCESS);
+ return ret;
}
int server_channel_handler::listener_get_data(channel *ch, message &msg)