Update for attribute changed callback and attribute getter
[platform/core/system/sensord.git] / src / client / sensor_listener.cpp
1 /*
2  * sensord
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #include "sensor_listener.h"
21
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>
27 #include <cmutex.h>
28
29 using namespace sensor;
30
31 static cmutex lock;
32
33 class listener_handler : public ipc::channel_handler
34 {
35 public:
36         listener_handler(sensor_listener *listener)
37         : m_listener(listener)
38         {}
39
40         void connected(ipc::channel *ch) {}
41         void disconnected(ipc::channel *ch)
42         {
43                 /* If channel->disconnect() is not explicitly called,
44                  * listener will be restored */
45                 m_listener->restore();
46         }
47
48         void read(ipc::channel *ch, ipc::message &msg)
49         {
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);
54                         }
55                         break;
56                 case CMD_LISTENER_ACC_EVENT:
57                         if (m_listener->get_accuracy_handler()) {
58                                 m_listener->get_accuracy_handler()->read(ch, msg);
59                         }
60                         break;
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);
64                         }
65                 } break;
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);
69                         }
70                 } break;
71                 default:
72                         _W("Invalid command message");
73                 }
74         }
75
76         void read_complete(ipc::channel *ch) {}
77         void error_caught(ipc::channel *ch, int error) {}
78
79 private:
80         sensor_listener *m_listener;
81 };
82
83 sensor_listener::sensor_listener(sensor_t sensor)
84 : m_id(0)
85 , m_sensor(reinterpret_cast<sensor_info *>(sensor))
86 , m_client(NULL)
87 , m_cmd_channel(NULL)
88 , m_evt_channel(NULL)
89 , m_handler(NULL)
90 , m_evt_handler(NULL)
91 , m_acc_handler(NULL)
92 , m_attr_int_changed_handler(NULL)
93 , m_attr_str_changed_handler(NULL)
94 , m_connected(false)
95 , m_started(false)
96 {
97         init();
98 }
99
100 sensor_listener::sensor_listener(sensor_t sensor, ipc::event_loop *loop)
101 : m_id(0)
102 , m_sensor(reinterpret_cast<sensor_info *>(sensor))
103 , m_client(NULL)
104 , m_cmd_channel(NULL)
105 , m_evt_channel(NULL)
106 , m_handler(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)
111 , m_loop(loop)
112 , m_connected(false)
113 , m_started(false)
114 {
115         init();
116 }
117
118 sensor_listener::~sensor_listener()
119 {
120         deinit();
121 }
122
123 bool sensor_listener::init(void)
124 {
125         m_client = new(std::nothrow) ipc::ipc_client(SENSOR_CHANNEL_PATH);
126         retvm_if(!m_client, false, "Failed to allocate memory");
127
128         m_handler = new(std::nothrow) listener_handler(this);
129         if (!m_handler) {
130                 delete m_client;
131                 return false;
132         }
133
134         if (!connect()) {
135                 delete m_handler;
136                 delete m_client;
137                 m_handler = NULL;
138                 m_client = NULL;
139                 return false;
140         }
141
142         return true;
143 }
144
145 void sensor_listener::deinit(void)
146 {
147         _D("Deinitializing..");
148         stop();
149         disconnect();
150
151         delete m_handler;
152         m_handler = NULL;
153
154         delete m_client;
155         m_client = NULL;
156
157         delete m_evt_handler;
158         m_evt_handler = NULL;
159
160         delete m_acc_handler;
161         m_acc_handler = NULL;
162
163         delete m_attr_int_changed_handler;
164         m_attr_int_changed_handler = NULL;
165
166         delete m_attr_str_changed_handler;
167         m_attr_str_changed_handler = NULL;
168
169         m_attributes_int.clear();
170         m_attributes_str.clear();
171         _D("Deinitialized..");
172 }
173
174 int sensor_listener::get_id(void)
175 {
176         return m_id;
177 }
178
179 sensor_t sensor_listener::get_sensor(void)
180 {
181         return static_cast<sensor_t>(m_sensor);
182 }
183
184 void sensor_listener::restore(void)
185 {
186         ret_if(!is_connected());
187         retm_if(!connect(), "Failed to restore listener");
188
189         _D("Restoring sensor listener");
190
191         /* Restore attributes/status */
192         if (m_started.load())
193                 start();
194
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]);
198
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]);
202
203         _D("Restored listener[%d]", get_id());
204 }
205
206 bool sensor_listener::connect(void)
207 {
208         m_cmd_channel = m_client->connect(NULL);
209         retvm_if(!m_cmd_channel, false, "Failed to connect to server");
210
211         m_evt_channel = m_client->connect(m_handler, m_loop, false);
212         retvm_if(!m_evt_channel, false, "Failed to connect to server");
213
214         ipc::message msg;
215         ipc::message reply;
216         cmd_listener_connect_t buf = {0, };
217
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);
222
223         m_evt_channel->read_sync(reply);
224         reply.disclose((char *)&buf);
225
226         m_id = buf.listener_id;
227         m_connected.store(true);
228
229         m_evt_channel->bind();
230
231         _I("Connected listener[%d] with sensor[%s]", get_id(), m_sensor->get_uri().c_str());
232
233         return true;
234 }
235
236 void sensor_listener::disconnect(void)
237 {
238         ret_if(!is_connected());
239         m_connected.store(false);
240
241         _D("Disconnecting..");
242
243         m_evt_channel->disconnect();
244         delete m_evt_channel;
245         m_evt_channel = NULL;
246
247         m_cmd_channel->disconnect();
248         delete m_cmd_channel;
249         m_cmd_channel = NULL;
250
251         _I("Disconnected[%d]", get_id());
252 }
253
254 bool sensor_listener::is_connected(void)
255 {
256         return m_connected.load();
257 }
258
259 ipc::channel_handler *sensor_listener::get_event_handler(void)
260 {
261         AUTOLOCK(lock);
262
263         return m_evt_handler;
264 }
265
266 void sensor_listener::set_event_handler(ipc::channel_handler *handler)
267 {
268         AUTOLOCK(lock);
269         if (m_evt_handler) {
270                 delete m_evt_handler;
271         }
272         m_evt_handler = handler;
273 }
274
275 void sensor_listener::unset_event_handler(void)
276 {
277         AUTOLOCK(lock);
278
279         delete m_evt_handler;
280         m_evt_handler = NULL;
281 }
282
283 ipc::channel_handler *sensor_listener::get_accuracy_handler(void)
284 {
285         AUTOLOCK(lock);
286         return m_acc_handler;
287 }
288
289 void sensor_listener::set_accuracy_handler(ipc::channel_handler *handler)
290 {
291         AUTOLOCK(lock);
292         if (m_acc_handler) {
293                 delete m_acc_handler;
294         }
295         m_acc_handler = handler;
296 }
297
298 void sensor_listener::unset_accuracy_handler(void)
299 {
300         AUTOLOCK(lock);
301         delete m_acc_handler;
302         m_acc_handler = NULL;
303 }
304
305 ipc::channel_handler *sensor_listener::get_attribute_int_changed_handler(void)
306 {
307         AUTOLOCK(lock);
308         return m_attr_int_changed_handler;
309 }
310
311 void sensor_listener::set_attribute_int_changed_handler(ipc::channel_handler *handler)
312 {
313         AUTOLOCK(lock);
314         if (m_attr_int_changed_handler) {
315                 delete m_attr_int_changed_handler;
316         }
317         m_attr_int_changed_handler = handler;
318 }
319
320 void sensor_listener::unset_attribute_int_changed_handler(void)
321 {
322         AUTOLOCK(lock);
323         delete m_attr_int_changed_handler;
324         m_attr_int_changed_handler = NULL;
325 }
326
327 ipc::channel_handler *sensor_listener::get_attribute_str_changed_handler(void)
328 {
329         AUTOLOCK(lock);
330         return m_attr_str_changed_handler;
331 }
332
333 void sensor_listener::set_attribute_str_changed_handler(ipc::channel_handler *handler)
334 {
335         AUTOLOCK(lock);
336         if (m_attr_str_changed_handler) {
337                 delete m_attr_str_changed_handler;
338         }
339         m_attr_str_changed_handler = handler;
340 }
341
342 void sensor_listener::unset_attribute_str_changed_handler(void)
343 {
344         AUTOLOCK(lock);
345         delete m_attr_str_changed_handler;
346         m_attr_str_changed_handler = NULL;
347 }
348
349 int sensor_listener::start(void)
350 {
351         ipc::message msg;
352         ipc::message reply;
353         cmd_listener_start_t buf;
354
355         retvm_if(!m_cmd_channel, -EINVAL, "Failed to connect to server");
356
357         buf.listener_id = m_id;
358         msg.set_type(CMD_LISTENER_START);
359         msg.enclose((char *)&buf, sizeof(buf));
360
361         m_cmd_channel->send_sync(msg);
362         m_cmd_channel->read_sync(reply);
363
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;
367         }
368
369         m_started.store(true);
370
371         _I("Listener[%d] started", get_id());
372
373         return OP_SUCCESS;
374 }
375
376 int sensor_listener::stop(void)
377 {
378         ipc::message msg;
379         ipc::message reply;
380         cmd_listener_stop_t buf;
381
382         retvm_if(!m_cmd_channel, -EINVAL, "Failed to connect to server");
383         retvm_if(!m_started.load(), -EAGAIN, "Already stopped");
384
385         buf.listener_id = m_id;
386         msg.set_type(CMD_LISTENER_STOP);
387         msg.enclose((char *)&buf, sizeof(buf));
388
389         m_cmd_channel->send_sync(msg);
390         m_cmd_channel->read_sync(reply);
391
392         if (reply.header()->err < 0) {
393                 _E("Failed to stop listener[%d]", get_id());
394                 return reply.header()->err;
395         }
396
397         m_started.store(false);
398
399         _I("Listener[%d] stopped", get_id());
400
401         return OP_SUCCESS;
402 }
403
404 int sensor_listener::get_interval(void)
405 {
406         auto it = m_attributes_int.find(SENSORD_ATTRIBUTE_INTERVAL);
407         retv_if(it == m_attributes_int.end(), -1);
408
409         return m_attributes_int[SENSORD_ATTRIBUTE_INTERVAL];
410 }
411
412 int sensor_listener::get_max_batch_latency(void)
413 {
414         auto it = m_attributes_int.find(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY);
415         retv_if(it == m_attributes_int.end(), -1);
416
417         return m_attributes_int[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY];
418 }
419
420 int sensor_listener::get_pause_policy(void)
421 {
422         auto it = m_attributes_int.find(SENSORD_ATTRIBUTE_PAUSE_POLICY);
423         retv_if(it == m_attributes_int.end(), -1);
424
425         return m_attributes_int[SENSORD_ATTRIBUTE_PAUSE_POLICY];
426 }
427
428 int sensor_listener::get_passive_mode(void)
429 {
430         auto it = m_attributes_int.find(SENSORD_ATTRIBUTE_PASSIVE_MODE);
431         retv_if(it == m_attributes_int.end(), -1);
432
433         return m_attributes_int[SENSORD_ATTRIBUTE_PASSIVE_MODE];
434 }
435
436 int sensor_listener::set_interval(unsigned int interval)
437 {
438         int _interval;
439
440         /* TODO: move this logic to server */
441         if (interval == 0)
442                 _interval = DEFAULT_INTERVAL;
443         else if (interval < (unsigned int)m_sensor->get_min_interval())
444                 _interval = m_sensor->get_min_interval();
445         else
446                 _interval = interval;
447
448         _I("Listener[%d] set interval[%u]", get_id(), _interval);
449
450         /* If it is not started, store the value only */
451         if (!m_started.load()) {
452                 m_attributes_int[SENSORD_ATTRIBUTE_INTERVAL] = _interval;
453                 return OP_SUCCESS;
454         }
455
456         return set_attribute(SENSORD_ATTRIBUTE_INTERVAL, _interval);
457 }
458
459 int sensor_listener::set_max_batch_latency(unsigned int max_batch_latency)
460 {
461         _I("Listener[%d] set max batch latency[%u]", get_id(), max_batch_latency);
462
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;
466                 return OP_SUCCESS;
467         }
468
469         return set_attribute(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY, max_batch_latency);
470 }
471
472 int sensor_listener::set_passive_mode(bool passive)
473 {
474         _I("Listener[%d] set passive mode[%d]", get_id(), passive);
475
476         return set_attribute(SENSORD_ATTRIBUTE_PASSIVE_MODE, passive);
477 }
478
479 int sensor_listener::flush(void)
480 {
481         _I("Listener[%d] flushes", get_id());
482
483         return set_attribute(SENSORD_ATTRIBUTE_FLUSH, 1);
484 }
485
486 int sensor_listener::set_attribute(int attribute, int value)
487 {
488         ipc::message msg;
489         ipc::message reply;
490         cmd_listener_attr_int_t buf;
491
492         retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server");
493
494         buf.listener_id = m_id;
495         buf.attribute = attribute;
496         buf.value = value;
497         msg.set_type(CMD_LISTENER_SET_ATTR_INT);
498         msg.enclose((char *)&buf, sizeof(buf));
499
500         m_cmd_channel->send_sync(msg);
501         m_cmd_channel->read_sync(reply);
502
503         if (reply.header()->err < 0)
504                 return reply.header()->err;
505
506         update_attribute(attribute, value);
507
508         return OP_SUCCESS;
509 }
510
511 int sensor_listener::get_attribute(int attribute, int* value)
512 {
513         ipc::message msg;
514         ipc::message reply;
515         cmd_listener_attr_int_t buf;
516
517         retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server");
518
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));
523
524         m_cmd_channel->send_sync(msg);
525         m_cmd_channel->read_sync(reply);
526
527         if (reply.header()->err < 0) {
528                 return reply.header()->err;
529         }
530
531         if (reply.header()->length && reply.body()) {
532                 *value = ((cmd_listener_attr_int_t *)reply.body())->value;
533                 return OP_SUCCESS;
534         }
535
536         return OP_ERROR;
537 }
538
539 void sensor_listener::update_attribute(int attribute, int value)
540 {
541         AUTOLOCK(lock);
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());
544 }
545
546 int sensor_listener::set_attribute(int attribute, const char *value, int len)
547 {
548         ipc::message msg;
549         ipc::message reply;
550         cmd_listener_attr_str_t *buf;
551         size_t size;
552
553         retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server");
554
555         size = sizeof(cmd_listener_attr_str_t) + len;
556
557         buf = (cmd_listener_attr_str_t *) new(std::nothrow) char[size];
558         retvm_if(!buf, -ENOMEM, "Failed to allocate memory");
559
560         msg.set_type(CMD_LISTENER_SET_ATTR_STR);
561         buf->listener_id = m_id;
562         buf->attribute = attribute;
563
564         memcpy(buf->value, value, len);
565         buf->len = len;
566
567         msg.enclose((char *)buf, size);
568
569         m_cmd_channel->send_sync(msg);
570         m_cmd_channel->read_sync(reply);
571
572         /* Message memory is released automatically after sending message,
573            so it doesn't need to free memory */
574
575         delete [] buf;
576
577         if (reply.header()->err < 0)
578                 return reply.header()->err;
579
580         update_attribute(attribute, value, len);
581
582         return OP_SUCCESS;
583 }
584
585 int sensor_listener::get_attribute(int attribute, char **value, int* len)
586 {
587         ipc::message msg;
588         ipc::message reply;
589         cmd_listener_attr_str_t buf;
590
591         buf.listener_id = m_id;
592         buf.attribute = attribute;
593
594         msg.set_type(CMD_LISTENER_GET_ATTR_STR);
595         msg.enclose((char *)&buf, sizeof(buf));
596         m_cmd_channel->send_sync(msg);
597
598         m_cmd_channel->read_sync(reply);
599         if (reply.header()->err < 0) {
600                 return reply.header()->err;
601         }
602
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);
609                 return OP_SUCCESS;
610         }
611
612         return OP_ERROR;
613 }
614
615 void sensor_listener::update_attribute(int attribute, const char *value, int len)
616 {
617         AUTOLOCK(lock);
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());
621 }
622
623 int sensor_listener::get_sensor_data(sensor_data_t *data)
624 {
625         ipc::message msg;
626         ipc::message reply;
627         cmd_listener_get_data_t buf;
628
629         retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server");
630
631         buf.listener_id = m_id;
632         msg.set_type(CMD_LISTENER_GET_DATA);
633         msg.enclose((char *)&buf, sizeof(buf));
634
635         m_cmd_channel->send_sync(msg);
636         m_cmd_channel->read_sync(reply);
637
638         reply.disclose((char *)&buf);
639         int size = sizeof(sensor_data_t);
640
641         if (buf.len > size || buf.len < 0) {
642                 data->accuracy = -1;
643                 data->value_count = 0;
644                 /* TODO: it should return OP_ERROR */
645                 return OP_SUCCESS;
646         }
647
648         memcpy(data, &buf.data, buf.len);
649
650         _D("Listener[%d] read sensor data", get_id());
651
652         return OP_SUCCESS;
653 }
654
655 int sensor_listener::get_sensor_data_list(sensor_data_t **data, int *count)
656 {
657         ipc::message msg;
658         ipc::message reply;
659         cmd_listener_get_data_list_t buf;
660
661         retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server");
662
663         buf.listener_id = m_id;
664         msg.set_type(CMD_LISTENER_GET_DATA_LIST);
665         msg.enclose((char *)&buf, sizeof(buf));
666
667         m_cmd_channel->send_sync(msg);
668         m_cmd_channel->read_sync(reply);
669
670         if (reply.header()->err < 0) {
671                 return reply.header()->err;
672         }
673
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];
676
677         retvm_if(!reply_buf, -ENOMEM, "Failed to allocate memory");
678
679         reply.disclose((char *)reply_buf);
680
681         if (reply_buf->len <= 0) {
682                 delete [] reply_buf;
683                 return OP_ERROR;
684         }
685
686         *count = reply_buf->data_count;
687         *data = (sensor_data_t*) malloc(reply_buf->len);
688
689         if (!(*data)) {
690                 _E("Memory allocation failed");
691                 delete [] reply_buf;
692                 return -ENOMEM;
693         }
694
695         memcpy(*data, reply_buf->data, reply_buf->len);
696
697         _D("Listener[%d] read sensor data list", get_id());
698         delete [] reply_buf;
699         return OP_SUCCESS;
700 }