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