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