4 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 #include "sensor_listener.h"
22 #include <channel_handler.h>
23 #include <sensor_log.h>
24 #include <sensor_types.h>
25 #include <command_types.h>
26 #include <ipc_client.h>
29 using namespace sensor;
33 class listener_handler : public ipc::channel_handler
36 listener_handler(sensor_listener *listener)
37 : m_listener(listener)
40 void connected(ipc::channel *ch) {}
41 void disconnected(ipc::channel *ch)
43 /* If channel->disconnect() is not explicitly called,
44 * listener will be restored */
45 m_listener->restore();
48 void read(ipc::channel *ch, ipc::message &msg)
50 switch (msg.header()->type) {
51 case CMD_LISTENER_EVENT:
52 if (m_listener->get_event_handler()) {
53 m_listener->get_event_handler()->read(ch, msg);
56 case CMD_LISTENER_ACC_EVENT:
57 if (m_listener->get_accuracy_handler()) {
58 m_listener->get_accuracy_handler()->read(ch, msg);
61 case CMD_LISTENER_SET_ATTR_INT: {
62 if (m_listener->get_attribute_int_changed_handler()) {
63 m_listener->get_attribute_int_changed_handler()->read(ch, msg);
66 case CMD_LISTENER_SET_ATTR_STR: {
67 if (m_listener->get_attribute_str_changed_handler()) {
68 m_listener->get_attribute_str_changed_handler()->read(ch, msg);
72 _W("Invalid command message");
76 void read_complete(ipc::channel *ch) {}
77 void error_caught(ipc::channel *ch, int error) {}
80 sensor_listener *m_listener;
83 sensor_listener::sensor_listener(sensor_t sensor)
85 , m_sensor(reinterpret_cast<sensor_info *>(sensor))
92 , m_attr_int_changed_handler(NULL)
93 , m_attr_str_changed_handler(NULL)
100 sensor_listener::sensor_listener(sensor_t sensor, ipc::event_loop *loop)
102 , m_sensor(reinterpret_cast<sensor_info *>(sensor))
104 , m_cmd_channel(NULL)
105 , m_evt_channel(NULL)
107 , m_evt_handler(NULL)
108 , m_acc_handler(NULL)
109 , m_attr_int_changed_handler(NULL)
110 , m_attr_str_changed_handler(NULL)
118 sensor_listener::~sensor_listener()
123 bool sensor_listener::init(void)
125 m_client = new(std::nothrow) ipc::ipc_client(SENSOR_CHANNEL_PATH);
126 retvm_if(!m_client, false, "Failed to allocate memory");
128 m_handler = new(std::nothrow) listener_handler(this);
145 void sensor_listener::deinit(void)
147 _D("Deinitializing..");
157 delete m_evt_handler;
158 m_evt_handler = NULL;
160 delete m_acc_handler;
161 m_acc_handler = NULL;
163 delete m_attr_int_changed_handler;
164 m_attr_int_changed_handler = NULL;
166 delete m_attr_str_changed_handler;
167 m_attr_str_changed_handler = NULL;
169 m_attributes_int.clear();
170 m_attributes_str.clear();
171 _D("Deinitialized..");
174 int sensor_listener::get_id(void)
179 sensor_t sensor_listener::get_sensor(void)
181 return static_cast<sensor_t>(m_sensor);
184 void sensor_listener::restore(void)
186 ret_if(!is_connected());
187 retm_if(!connect(), "Failed to restore listener");
189 _D("Restoring sensor listener");
191 /* Restore attributes/status */
192 if (m_started.load())
195 auto interval = m_attributes_int.find(SENSORD_ATTRIBUTE_INTERVAL);
196 if (interval != m_attributes_int.end())
197 set_interval(m_attributes_int[SENSORD_ATTRIBUTE_INTERVAL]);
199 auto latency = m_attributes_int.find(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY);
200 if (latency != m_attributes_int.end())
201 set_max_batch_latency(m_attributes_int[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY]);
203 _D("Restored listener[%d]", get_id());
206 bool sensor_listener::connect(void)
208 m_cmd_channel = m_client->connect(NULL);
209 retvm_if(!m_cmd_channel, false, "Failed to connect to server");
211 m_evt_channel = m_client->connect(m_handler, m_loop, false);
212 retvm_if(!m_evt_channel, false, "Failed to connect to server");
216 cmd_listener_connect_t buf = {0, };
218 memcpy(buf.sensor, m_sensor->get_uri().c_str(), m_sensor->get_uri().size());
219 msg.set_type(CMD_LISTENER_CONNECT);
220 msg.enclose((const char *)&buf, sizeof(buf));
221 m_evt_channel->send_sync(msg);
223 m_evt_channel->read_sync(reply);
224 reply.disclose((char *)&buf);
226 m_id = buf.listener_id;
227 m_connected.store(true);
229 m_evt_channel->bind();
231 _I("Connected listener[%d] with sensor[%s]", get_id(), m_sensor->get_uri().c_str());
236 void sensor_listener::disconnect(void)
238 ret_if(!is_connected());
239 m_connected.store(false);
241 _D("Disconnecting..");
243 m_evt_channel->disconnect();
244 delete m_evt_channel;
245 m_evt_channel = NULL;
247 m_cmd_channel->disconnect();
248 delete m_cmd_channel;
249 m_cmd_channel = NULL;
251 _I("Disconnected[%d]", get_id());
254 bool sensor_listener::is_connected(void)
256 return m_connected.load();
259 ipc::channel_handler *sensor_listener::get_event_handler(void)
263 return m_evt_handler;
266 void sensor_listener::set_event_handler(ipc::channel_handler *handler)
270 delete m_evt_handler;
272 m_evt_handler = handler;
275 void sensor_listener::unset_event_handler(void)
279 delete m_evt_handler;
280 m_evt_handler = NULL;
283 ipc::channel_handler *sensor_listener::get_accuracy_handler(void)
286 return m_acc_handler;
289 void sensor_listener::set_accuracy_handler(ipc::channel_handler *handler)
293 delete m_acc_handler;
295 m_acc_handler = handler;
298 void sensor_listener::unset_accuracy_handler(void)
301 delete m_acc_handler;
302 m_acc_handler = NULL;
305 ipc::channel_handler *sensor_listener::get_attribute_int_changed_handler(void)
308 return m_attr_int_changed_handler;
311 void sensor_listener::set_attribute_int_changed_handler(ipc::channel_handler *handler)
314 if (m_attr_int_changed_handler) {
315 delete m_attr_int_changed_handler;
317 m_attr_int_changed_handler = handler;
320 void sensor_listener::unset_attribute_int_changed_handler(void)
323 delete m_attr_int_changed_handler;
324 m_attr_int_changed_handler = NULL;
327 ipc::channel_handler *sensor_listener::get_attribute_str_changed_handler(void)
330 return m_attr_str_changed_handler;
333 void sensor_listener::set_attribute_str_changed_handler(ipc::channel_handler *handler)
336 if (m_attr_str_changed_handler) {
337 delete m_attr_str_changed_handler;
339 m_attr_str_changed_handler = handler;
342 void sensor_listener::unset_attribute_str_changed_handler(void)
345 delete m_attr_str_changed_handler;
346 m_attr_str_changed_handler = NULL;
349 int sensor_listener::start(void)
353 cmd_listener_start_t buf;
355 retvm_if(!m_cmd_channel, -EINVAL, "Failed to connect to server");
357 buf.listener_id = m_id;
358 msg.set_type(CMD_LISTENER_START);
359 msg.enclose((char *)&buf, sizeof(buf));
361 m_cmd_channel->send_sync(msg);
362 m_cmd_channel->read_sync(reply);
364 if (reply.header()->err < 0) {
365 _E("Failed to start listener[%d], sensor[%s]", get_id(), m_sensor->get_uri().c_str());
366 return reply.header()->err;
369 m_started.store(true);
371 _I("Listener[%d] started", get_id());
376 int sensor_listener::stop(void)
380 cmd_listener_stop_t buf;
382 retvm_if(!m_cmd_channel, -EINVAL, "Failed to connect to server");
383 retvm_if(!m_started.load(), -EAGAIN, "Already stopped");
385 buf.listener_id = m_id;
386 msg.set_type(CMD_LISTENER_STOP);
387 msg.enclose((char *)&buf, sizeof(buf));
389 m_cmd_channel->send_sync(msg);
390 m_cmd_channel->read_sync(reply);
392 if (reply.header()->err < 0) {
393 _E("Failed to stop listener[%d]", get_id());
394 return reply.header()->err;
397 m_started.store(false);
399 _I("Listener[%d] stopped", get_id());
404 int sensor_listener::get_interval(void)
406 auto it = m_attributes_int.find(SENSORD_ATTRIBUTE_INTERVAL);
407 retv_if(it == m_attributes_int.end(), -1);
409 return m_attributes_int[SENSORD_ATTRIBUTE_INTERVAL];
412 int sensor_listener::get_max_batch_latency(void)
414 auto it = m_attributes_int.find(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY);
415 retv_if(it == m_attributes_int.end(), -1);
417 return m_attributes_int[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY];
420 int sensor_listener::get_pause_policy(void)
422 auto it = m_attributes_int.find(SENSORD_ATTRIBUTE_PAUSE_POLICY);
423 retv_if(it == m_attributes_int.end(), -1);
425 return m_attributes_int[SENSORD_ATTRIBUTE_PAUSE_POLICY];
428 int sensor_listener::get_passive_mode(void)
430 auto it = m_attributes_int.find(SENSORD_ATTRIBUTE_PASSIVE_MODE);
431 retv_if(it == m_attributes_int.end(), -1);
433 return m_attributes_int[SENSORD_ATTRIBUTE_PASSIVE_MODE];
436 int sensor_listener::set_interval(unsigned int interval)
440 /* TODO: move this logic to server */
442 _interval = DEFAULT_INTERVAL;
443 else if (interval < (unsigned int)m_sensor->get_min_interval())
444 _interval = m_sensor->get_min_interval();
446 _interval = interval;
448 _I("Listener[%d] set interval[%u]", get_id(), _interval);
450 /* If it is not started, store the value only */
451 if (!m_started.load()) {
452 m_attributes_int[SENSORD_ATTRIBUTE_INTERVAL] = _interval;
456 return set_attribute(SENSORD_ATTRIBUTE_INTERVAL, _interval);
459 int sensor_listener::set_max_batch_latency(unsigned int max_batch_latency)
461 _I("Listener[%d] set max batch latency[%u]", get_id(), max_batch_latency);
463 /* If it is not started, store the value only */
464 if (!m_started.load()) {
465 m_attributes_int[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY] = max_batch_latency;
469 return set_attribute(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY, max_batch_latency);
472 int sensor_listener::set_passive_mode(bool passive)
474 _I("Listener[%d] set passive mode[%d]", get_id(), passive);
476 return set_attribute(SENSORD_ATTRIBUTE_PASSIVE_MODE, passive);
479 int sensor_listener::flush(void)
481 _I("Listener[%d] flushes", get_id());
483 return set_attribute(SENSORD_ATTRIBUTE_FLUSH, 1);
486 int sensor_listener::set_attribute(int attribute, int value)
490 cmd_listener_attr_int_t buf;
492 retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server");
494 buf.listener_id = m_id;
495 buf.attribute = attribute;
497 msg.set_type(CMD_LISTENER_SET_ATTR_INT);
498 msg.enclose((char *)&buf, sizeof(buf));
500 m_cmd_channel->send_sync(msg);
501 m_cmd_channel->read_sync(reply);
503 if (reply.header()->err < 0)
504 return reply.header()->err;
506 update_attribute(attribute, value);
511 int sensor_listener::get_attribute(int attribute, int* value)
515 cmd_listener_attr_int_t buf;
517 retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server");
519 buf.listener_id = m_id;
520 buf.attribute = attribute;
521 msg.set_type(CMD_LISTENER_GET_ATTR_INT);
522 msg.enclose((char *)&buf, sizeof(buf));
524 m_cmd_channel->send_sync(msg);
525 m_cmd_channel->read_sync(reply);
527 if (reply.header()->err < 0) {
528 return reply.header()->err;
531 if (reply.header()->length && reply.body()) {
532 *value = ((cmd_listener_attr_int_t *)reply.body())->value;
539 void sensor_listener::update_attribute(int attribute, int value)
542 m_attributes_int[attribute] = value;
543 _I("Update_attribute(int) listener[%d] attribute[%d] value[%d] attributes size[%d]", get_id(), attribute, value, m_attributes_int.size());
546 int sensor_listener::set_attribute(int attribute, const char *value, int len)
550 cmd_listener_attr_str_t *buf;
553 retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server");
555 size = sizeof(cmd_listener_attr_str_t) + len;
557 buf = (cmd_listener_attr_str_t *) new(std::nothrow) char[size];
558 retvm_if(!buf, -ENOMEM, "Failed to allocate memory");
560 msg.set_type(CMD_LISTENER_SET_ATTR_STR);
561 buf->listener_id = m_id;
562 buf->attribute = attribute;
564 memcpy(buf->value, value, len);
567 msg.enclose((char *)buf, size);
569 m_cmd_channel->send_sync(msg);
570 m_cmd_channel->read_sync(reply);
572 /* Message memory is released automatically after sending message,
573 so it doesn't need to free memory */
577 if (reply.header()->err < 0)
578 return reply.header()->err;
580 update_attribute(attribute, value, len);
585 int sensor_listener::get_attribute(int attribute, char **value, int* len)
589 cmd_listener_attr_str_t buf;
591 buf.listener_id = m_id;
592 buf.attribute = attribute;
594 msg.set_type(CMD_LISTENER_GET_ATTR_STR);
595 msg.enclose((char *)&buf, sizeof(buf));
596 m_cmd_channel->send_sync(msg);
598 m_cmd_channel->read_sync(reply);
599 if (reply.header()->err < 0) {
600 return reply.header()->err;
603 if (reply.header()->length && reply.body()) {
604 cmd_listener_attr_str_t * recv_buf = (cmd_listener_attr_str_t *)reply.body();
605 char* p = (char *)recv_buf->value;
606 *len = recv_buf->len;
607 *value = (char *) malloc(*len);
608 std::copy(p, p + recv_buf->len, *value);
615 void sensor_listener::update_attribute(int attribute, const char *value, int len)
618 m_attributes_str[attribute].clear();
619 m_attributes_str[attribute].insert(m_attributes_str[attribute].begin(), value, value + len);
620 _I("Update_attribute(str) listener[%d] attribute[%d] value[%s] attributes size[%zu]", get_id(), attribute, value, m_attributes_int.size());
623 int sensor_listener::get_sensor_data(sensor_data_t *data)
627 cmd_listener_get_data_t buf;
629 retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server");
631 buf.listener_id = m_id;
632 msg.set_type(CMD_LISTENER_GET_DATA);
633 msg.enclose((char *)&buf, sizeof(buf));
635 m_cmd_channel->send_sync(msg);
636 m_cmd_channel->read_sync(reply);
638 reply.disclose((char *)&buf);
639 int size = sizeof(sensor_data_t);
641 if (buf.len > size || buf.len < 0) {
643 data->value_count = 0;
644 /* TODO: it should return OP_ERROR */
648 memcpy(data, &buf.data, buf.len);
650 _D("Listener[%d] read sensor data", get_id());
655 int sensor_listener::get_sensor_data_list(sensor_data_t **data, int *count)
659 cmd_listener_get_data_list_t buf;
661 retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server");
663 buf.listener_id = m_id;
664 msg.set_type(CMD_LISTENER_GET_DATA_LIST);
665 msg.enclose((char *)&buf, sizeof(buf));
667 m_cmd_channel->send_sync(msg);
668 m_cmd_channel->read_sync(reply);
670 if (reply.header()->err < 0) {
671 return reply.header()->err;
674 size_t size = reply.size();
675 cmd_listener_get_data_list_t* reply_buf = (cmd_listener_get_data_list_t *) new(std::nothrow) char[size];
677 retvm_if(!reply_buf, -ENOMEM, "Failed to allocate memory");
679 reply.disclose((char *)reply_buf);
681 if (reply_buf->len <= 0) {
686 *count = reply_buf->data_count;
687 *data = (sensor_data_t*) malloc(reply_buf->len);
690 _E("Memory allocation failed");
695 memcpy(*data, reply_buf->data, reply_buf->len);
697 _D("Listener[%d] read sensor data list", get_id());