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