sensord: add lazy binding event handler to event loop
[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
28 using namespace sensor;
29
30 class listener_handler : public ipc::channel_handler
31 {
32 public:
33         listener_handler(sensor_listener *listener)
34         : m_listener(listener)
35         {}
36         void connected(ipc::channel *ch) {}
37         void disconnected(ipc::channel *ch)
38         {
39                 /* If channel->disconnect() is not explicitly called,
40                  * listener will be restored */
41                 m_listener->restore();
42         }
43
44         void read(ipc::channel *ch, ipc::message &msg)
45         {
46                 switch (msg.header()->type) {
47                 case CMD_LISTENER_EVENT:
48                         if (m_listener->get_event_handler())
49                                 m_listener->get_event_handler()->read(ch, msg);
50                         break;
51                 case CMD_LISTENER_ACC_EVENT:
52                         if (m_listener->get_accuracy_handler())
53                                 m_listener->get_accuracy_handler()->read(ch, msg);
54                         break;
55                 }
56         }
57
58         void read_complete(ipc::channel *ch) {}
59         void error_caught(ipc::channel *ch, int error) {}
60
61 private:
62         sensor_listener *m_listener;
63 };
64
65 sensor_listener::sensor_listener(sensor_t sensor)
66 : m_id(0)
67 , m_sensor(reinterpret_cast<sensor_info *>(sensor))
68 , m_client(NULL)
69 , m_cmd_channel(NULL)
70 , m_evt_channel(NULL)
71 , m_handler(NULL)
72 , m_evt_handler(NULL)
73 , m_acc_handler(NULL)
74 , m_connected(false)
75 , m_started(false)
76 {
77         init();
78 }
79
80 sensor_listener::~sensor_listener()
81 {
82         deinit();
83 }
84
85 bool sensor_listener::init(void)
86 {
87         m_client = new(std::nothrow) ipc::ipc_client(SENSOR_CHANNEL_PATH);
88         retvm_if(!m_client, false, "Failed to allocate memory");
89
90         m_handler = new(std::nothrow) listener_handler(this);
91         if (!m_handler) {
92                 delete m_client;
93                 return false;
94         }
95
96         if (!connect()) {
97                 delete m_handler;
98                 delete m_client;
99                 m_handler = NULL;
100                 m_client = NULL;
101                 return false;
102         }
103
104         return true;
105 }
106
107 void sensor_listener::deinit(void)
108 {
109         disconnect();
110
111         delete m_handler;
112         m_handler = NULL;
113
114         delete m_client;
115         m_client = NULL;
116
117         m_attributes.clear();
118 }
119
120 int sensor_listener::get_id(void)
121 {
122         return m_id;
123 }
124
125 sensor_t sensor_listener::get_sensor(void)
126 {
127         return static_cast<sensor_t>(m_sensor);
128 }
129
130 void sensor_listener::restore(void)
131 {
132         ret_if(!is_connected());
133         retm_if(!connect(), "Failed to restore listener");
134
135         /* Restore attributes/status */
136         if (m_started.load())
137                 start();
138
139         auto interval = m_attributes.find(SENSORD_ATTRIBUTE_INTERVAL);
140         if (interval != m_attributes.end())
141                 set_interval(m_attributes[SENSORD_ATTRIBUTE_INTERVAL]);
142
143         auto latency = m_attributes.find(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY);
144         if (latency != m_attributes.end())
145                 set_max_batch_latency(m_attributes[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY]);
146
147         _D("Restored listener[%d]", get_id());
148 }
149
150 bool sensor_listener::connect(void)
151 {
152         m_cmd_channel = m_client->connect(NULL);
153         retvm_if(!m_cmd_channel, false, "Failed to connect to server");
154
155         m_evt_channel = m_client->connect(m_handler, &m_loop, false);
156         retvm_if(!m_evt_channel, false, "Failed to connect to server");
157
158         ipc::message msg;
159         ipc::message reply;
160         cmd_listener_connect_t buf = {0, };
161
162         memcpy(buf.sensor, m_sensor->get_uri().c_str(), m_sensor->get_uri().size());
163         msg.set_type(CMD_LISTENER_CONNECT);
164         msg.enclose((const char *)&buf, sizeof(buf));
165         m_evt_channel->send_sync(&msg);
166
167         m_evt_channel->read_sync(reply);
168         reply.disclose((char *)&buf);
169
170         m_id = buf.listener_id;
171         m_connected.store(true);
172
173         m_evt_channel->bind();
174
175         _D("Listener ID[%d]", get_id());
176
177         return true;
178 }
179
180 void sensor_listener::disconnect(void)
181 {
182         ret_if(!is_connected());
183         m_connected.store(false);
184
185         ipc::message msg;
186         ipc::message reply;
187
188         msg.set_type(CMD_LISTENER_DISCONNECT);
189         m_evt_channel->send_sync(&msg);
190
191         m_evt_channel->read_sync(reply);
192         m_evt_channel->disconnect();
193
194         delete m_evt_channel;
195         m_evt_channel = NULL;
196
197         m_cmd_channel->disconnect();
198         delete m_cmd_channel;
199         m_cmd_channel = NULL;
200
201         _I("Disconnected[%d]", get_id());
202 }
203
204 bool sensor_listener::is_connected(void)
205 {
206         return m_connected.load();
207 }
208
209 ipc::channel_handler *sensor_listener::get_event_handler(void)
210 {
211         return m_evt_handler;
212 }
213
214 void sensor_listener::set_event_handler(ipc::channel_handler *handler)
215 {
216         m_evt_handler = handler;
217 }
218
219 void sensor_listener::unset_event_handler(void)
220 {
221         delete m_evt_handler;
222         m_evt_handler = NULL;
223 }
224
225 ipc::channel_handler *sensor_listener::get_accuracy_handler(void)
226 {
227         return m_acc_handler;
228 }
229
230 void sensor_listener::set_accuracy_handler(ipc::channel_handler *handler)
231 {
232         m_acc_handler = handler;
233 }
234
235 void sensor_listener::unset_accuracy_handler(void)
236 {
237         delete m_acc_handler;
238         m_acc_handler = NULL;
239 }
240
241 int sensor_listener::start(void)
242 {
243         ipc::message msg;
244         ipc::message reply;
245         cmd_listener_start_t buf;
246
247         retvm_if(!m_cmd_channel, -EINVAL, "Failed to connect to server");
248
249         buf.listener_id = m_id;
250         msg.set_type(CMD_LISTENER_START);
251         msg.enclose((char *)&buf, sizeof(buf));
252
253         m_cmd_channel->send_sync(&msg);
254         m_cmd_channel->read_sync(reply);
255
256         if (reply.header()->err < 0)
257                 return reply.header()->err;
258
259         m_started.store(true);
260
261         return OP_SUCCESS;
262 }
263
264 int sensor_listener::stop(void)
265 {
266         ipc::message msg;
267         ipc::message reply;
268         cmd_listener_stop_t buf;
269
270         retvm_if(!m_cmd_channel, -EINVAL, "Failed to connect to server");
271         retvm_if(!m_started.load(), -EAGAIN, "Already stopped");
272
273         buf.listener_id = m_id;
274         msg.set_type(CMD_LISTENER_STOP);
275         msg.enclose((char *)&buf, sizeof(buf));
276
277         m_cmd_channel->send_sync(&msg);
278         m_cmd_channel->read_sync(reply);
279
280         if (reply.header()->err < 0)
281                 return reply.header()->err;
282
283         m_started.store(false);
284
285         return OP_SUCCESS;
286 }
287
288 int sensor_listener::get_interval(void)
289 {
290         auto it = m_attributes.find(SENSORD_ATTRIBUTE_INTERVAL);
291         retv_if(it == m_attributes.end(), -1);
292
293         return m_attributes[SENSORD_ATTRIBUTE_INTERVAL];
294 }
295
296 int sensor_listener::get_max_batch_latency(void)
297 {
298         auto it = m_attributes.find(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY);
299         retv_if(it == m_attributes.end(), -1);
300
301         return m_attributes[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY];
302 }
303
304 int sensor_listener::get_pause_policy(void)
305 {
306         auto it = m_attributes.find(SENSORD_ATTRIBUTE_PAUSE_POLICY);
307         retv_if(it == m_attributes.end(), -1);
308
309         return m_attributes[SENSORD_ATTRIBUTE_PAUSE_POLICY];
310 }
311
312 int sensor_listener::get_passive_mode(void)
313 {
314         auto it = m_attributes.find(SENSORD_ATTRIBUTE_PASSIVE_MODE);
315         retv_if(it == m_attributes.end(), -1);
316
317         return m_attributes[SENSORD_ATTRIBUTE_PASSIVE_MODE];
318 }
319
320 int sensor_listener::set_interval(unsigned int interval)
321 {
322         int _interval;
323
324         /* TODO: move this logic to server */
325         if (interval == 0)
326                 _interval = DEFAULT_INTERVAL;
327         else if (interval < (unsigned int)m_sensor->get_min_interval())
328                 _interval = m_sensor->get_min_interval();
329         else
330                 _interval = interval;
331
332         return set_attribute(SENSORD_ATTRIBUTE_INTERVAL, _interval);
333 }
334
335 int sensor_listener::set_max_batch_latency(unsigned int max_batch_latency)
336 {
337         return set_attribute(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY, max_batch_latency);
338 }
339
340 int sensor_listener::set_passive_mode(bool passive)
341 {
342         return set_attribute(SENSORD_ATTRIBUTE_PASSIVE_MODE, passive);
343 }
344
345 int sensor_listener::flush(void)
346 {
347         return set_attribute(SENSORD_ATTRIBUTE_FLUSH, 1);
348 }
349
350 int sensor_listener::set_attribute(int attribute, int value)
351 {
352         ipc::message msg;
353         ipc::message reply;
354         cmd_listener_attr_int_t buf;
355
356         retvm_if(!m_cmd_channel, false, "Failed to connect to server");
357
358         buf.listener_id = m_id;
359         buf.attribute = attribute;
360         buf.value = value;
361         msg.set_type(CMD_LISTENER_ATTR_INT);
362         msg.enclose((char *)&buf, sizeof(buf));
363
364         m_cmd_channel->send_sync(&msg);
365         m_cmd_channel->read_sync(reply);
366
367         if (reply.header()->err < 0)
368                 return reply.header()->err;
369
370         m_attributes[attribute] = value;
371
372         return OP_SUCCESS;
373 }
374
375 int sensor_listener::set_attribute(int attribute, const char *value, int len)
376 {
377         ipc::message msg;
378         ipc::message reply;
379         cmd_listener_attr_str_t buf;
380
381         retvm_if(!m_cmd_channel, false, "Failed to connect to server");
382
383         msg.set_type(CMD_LISTENER_ATTR_STR);
384         buf.listener_id = m_id;
385         buf.attribute = attribute;
386         memcpy(buf.value, value, len);
387         buf.len = len;
388
389         msg.enclose((char *)&buf, sizeof(buf) + len);
390
391         m_cmd_channel->send_sync(&msg);
392         m_cmd_channel->read_sync(reply);
393
394         return reply.header()->err;
395 }
396
397 int sensor_listener::get_sensor_data(sensor_data_t *data)
398 {
399         ipc::message msg;
400         ipc::message reply;
401         cmd_listener_get_data_t buf;
402
403         retvm_if(!m_cmd_channel, false, "Failed to connect to server");
404
405         buf.listener_id = m_id;
406         msg.set_type(CMD_LISTENER_GET_DATA);
407         msg.enclose((char *)&buf, sizeof(buf));
408
409         m_cmd_channel->send_sync(&msg);
410         m_cmd_channel->read_sync(reply);
411
412         reply.disclose((char *)&buf);
413         int size = sizeof(sensor_data_t);
414
415         if (buf.len > size || buf.len < 0) {
416                 data->accuracy = -1;
417                 data->value_count = 0;
418                 /* TODO: it should return OP_ERROR */
419                 return OP_SUCCESS;
420         }
421
422         memcpy(data, &buf.data, buf.len);
423
424         return OP_SUCCESS;
425 }
426