Refactoring: sensor_provider class
[platform/core/api/sensor.git] / src / api / sensor-provider.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-provider.h"
21
22 #include <glib.h>
23 #include <message.h>
24 #include <socket.h>
25 #include <sensor-log-private.h>
26 #include <sensor-types-private.h>
27 #include <sensor-utils.h>
28 #include <command-types.h>
29 #include <lock.h>
30
31 #include <cfloat>
32 #include <cmath>
33
34 #define DEFAULT_RESOLUTION 0.1
35
36 using namespace sensor;
37
38 static gboolean provider_handler(GIOChannel *ch, GIOCondition condition, gpointer data)
39 {
40         sensor_provider *p = (sensor_provider*) data;
41         unsigned int cond = (unsigned int)condition;
42
43         if (cond & (G_IO_HUP)) {
44                 p->restore();
45                 return false;
46         }
47
48         ipc::message msg;
49         bool ret = p->read(msg);
50         if (!ret)
51                 return false;
52
53         p->handle(msg);
54
55         return true;
56 }
57
58 sensor_provider::sensor_provider(const char *uri)
59 : m_connected(false)
60 , m_start_cb(NULL)
61 , m_stop_cb(NULL)
62 , m_interval_changed_cb(NULL)
63 , m_attribute_str_cb(NULL)
64 , m_start_user_data(NULL)
65 , m_stop_user_data(NULL)
66 , m_interval_changed_user_data(NULL)
67 , m_attribute_str_user_data(NULL)
68 , g_src(NULL)
69 {
70         init(uri);
71         m_loop = g_main_loop_new(NULL, FALSE);
72 }
73
74 sensor_provider::~sensor_provider()
75 {
76         deinit();
77
78         if (m_loop) {
79                 g_main_loop_quit(m_loop);
80                 g_main_loop_unref(m_loop);
81                 m_loop = NULL;
82         }
83 }
84
85 bool sensor_provider::init(const char *uri)
86 {
87         m_sensor.set_uri(uri);
88         m_sensor.set_min_range(-FLT_MAX);
89         m_sensor.set_max_range(FLT_MAX);
90         m_sensor.set_resolution(DEFAULT_RESOLUTION);
91         /* TODO: temporary walkaround */
92         const char *priv = sensor::utils::get_privilege(uri);
93         m_sensor.set_privilege(priv);
94
95         return true;
96 }
97
98 void sensor_provider::deinit(void)
99 {
100         disconnect();
101 }
102
103 const char *sensor_provider::get_uri(void)
104 {
105         return m_sensor.get_uri().c_str();
106 }
107
108 sensor_info *sensor_provider::get_sensor_info(void)
109 {
110         return &m_sensor;
111 }
112
113 int sensor_provider::serialize(sensor_info *info, char **bytes)
114 {
115         int size;
116         raw_data_t *raw = new(std::nothrow) raw_data_t;
117         retvm_if(!raw, -ENOMEM, "Failed to allocated memory");
118
119         info->serialize(*raw);
120
121         *bytes = (char *) malloc(raw->size());
122
123         if (!(*bytes)) {
124                 delete(raw);
125                 _E("Failed to allocate memory");
126                 return -ENOMEM;
127         }
128
129         std::copy(raw->begin(), raw->end(), *bytes);
130
131         size = raw->size();
132         delete raw;
133
134         return size;
135 }
136
137 int sensor_provider::send_sensor_info(sensor_info *info)
138 {
139         char *bytes;
140         int size;
141
142         size = serialize(info, &bytes);
143         if (size < 0)
144                 return OP_ERROR;
145
146         ipc::message msg((const char *)bytes, size);
147         msg.set_type(CMD_PROVIDER_CONNECT);
148
149         bool ret = send(msg);
150         if (!ret)
151                 return OP_ERROR;
152         return OP_SUCCESS;
153 }
154
155 int sensor_provider::connect(void)
156 {
157         m_socket = new(std::nothrow) ipc::socket();
158         retvm_if(!m_socket, NULL, "Failed to allocate memory");
159
160         if (!m_socket->create(SENSOR_CHANNEL_PATH)) {
161                 delete m_socket;
162                 return 0;
163         }
164
165         if (!m_socket->connect())
166                 return 0;
167
168         GIOChannel *ch = NULL;
169
170         ch = g_io_channel_unix_new(m_socket->get_fd());
171         retvm_if(!ch, NULL, "Failed to create g_io_channel_unix_new");
172
173         g_src = g_io_create_watch(ch, (GIOCondition) (ipc::EVENT_IN | ipc::EVENT_HUP | ipc::EVENT_NVAL));
174         g_io_channel_unref(ch);
175         if (!g_src) {
176                 _E("Failed to create g_io_create_watch");
177                 return OP_ERROR;
178         }
179
180         g_source_set_callback(g_src, (GSourceFunc) provider_handler, this, NULL);
181         g_source_attach(g_src, g_main_loop_get_context(m_loop));
182         g_source_unref(g_src);
183
184         /* serialize and send sensor info */
185         send_sensor_info(get_sensor_info());
186
187         /* check error */
188         ipc::message reply;
189
190         bool ret = read(reply);
191         if (!ret)
192                 return OP_ERROR;
193         retv_if(reply.header()->err < 0, reply.header()->err);
194
195         m_connected.store(true);
196
197         _I("Provider URI[%s]", get_uri());
198
199         return OP_SUCCESS;
200 }
201
202 bool sensor_provider::disconnect(void)
203 {
204         AUTOLOCK(m_cmutex);
205         retv_if(!is_connected(), false);
206
207         if (g_src && !g_source_is_destroyed(g_src)) {
208                 g_source_destroy(g_src);
209                 g_src = NULL;
210         }
211
212         m_connected.store(false);
213         delete m_socket;
214         m_socket = NULL;
215
216         _I("Disconnected[%s]", get_uri());
217         return true;
218 }
219
220 bool sensor_provider::restore(void)
221 {
222         retv_if(!is_connected(), false);
223         retvm_if(connect(), false, "Failed to restore provider");
224
225         _D("Restored provider[%s]", get_uri());
226         return true;
227 }
228
229 int sensor_provider::publish(const sensor_data_t &data)
230 {
231         ipc::message msg;
232         msg.set_type(CMD_PROVIDER_PUBLISH);
233         msg.enclose((const void *)(&data), sizeof(data));
234
235         bool ret = send(msg);
236         if (!ret)
237                 return OP_ERROR;
238
239         return OP_SUCCESS;
240 }
241
242 int sensor_provider::publish(const sensor_data_t data[], const int count)
243 {
244         ipc::message msg;
245         msg.set_type(CMD_PROVIDER_PUBLISH);
246         msg.enclose((const void *)data, sizeof(sensor_data_t) * count);
247
248         send(msg);
249
250         return OP_SUCCESS;
251 }
252
253 bool sensor_provider::is_connected(void)
254 {
255         return m_connected.load();
256 }
257
258 void sensor_provider::set_start_cb(sensord_provider_start_cb cb, void *user_data)
259 {
260         m_start_cb = cb;
261         m_start_user_data = user_data;
262 }
263
264 void sensor_provider::set_stop_cb(sensord_provider_stop_cb cb, void *user_data)
265 {
266         m_stop_cb = cb;
267         m_stop_user_data = user_data;
268 }
269
270 void sensor_provider::set_interval_cb(sensord_provider_interval_changed_cb cb, void *user_data)
271 {
272         m_interval_changed_cb = cb;
273         m_interval_changed_user_data = user_data;
274 }
275
276 void sensor_provider::set_attribute_str_cb(sensord_provider_attribute_str_cb cb, void *user_data)
277 {
278         m_attribute_str_cb = cb;
279         m_attribute_str_user_data = user_data;
280 }
281
282 bool sensor_provider::read(ipc::message &msg)
283 {
284         AUTOLOCK(m_cmutex);
285         if (!m_socket) {
286                 _E("Socket is not connected");
287                 return false;
288         }
289
290         ipc::message_header header;
291         ssize_t size = 0;
292         char buf[MAX_MSG_CAPACITY];
293
294         /* header */
295         size = m_socket->recv(&header, sizeof(ipc::message_header), false);
296         if (size <= 0)
297                 return false;
298
299         // check error from header
300         if (header.err != 0) {
301                 msg.header()->err = header.err;
302                 return false;
303         }
304
305         /* body */
306         if (header.length >= MAX_MSG_CAPACITY) {
307                 _E("header.length error %u", header.length);
308                 return false;
309         }
310
311         if (header.length > 0) {
312                 size = m_socket->recv(&buf, header.length, false);
313                 if (size <= 0)
314                         return false;
315         }
316
317         buf[header.length] = '\0';
318         msg.enclose(reinterpret_cast<const void *>(buf), header.length);
319         msg.set_type(header.type);
320         msg.header()->err = header.err;
321
322         return true;
323 }
324
325 void sensor_provider::handle(ipc::message &msg)
326 {
327         switch (msg.type()) {
328         case CMD_PROVIDER_START:
329                 if (m_start_cb)
330                         m_start_cb(this, m_start_user_data);
331                 break;
332         case CMD_PROVIDER_STOP:
333                 if (m_stop_cb)
334                         m_stop_cb(this, m_stop_user_data);
335                 break;
336         case CMD_PROVIDER_ATTR_INT:
337                 cmd_provider_attr_int_t buf;
338                 msg.disclose((char *)&buf, sizeof(buf));
339
340                 if (buf.attribute == SENSORD_ATTRIBUTE_INTERVAL && m_interval_changed_cb)
341                         m_interval_changed_cb(this, buf.value, m_interval_changed_user_data);
342                 break;
343         case CMD_PROVIDER_ATTR_STR:
344                 cmd_provider_attr_str_t *attr;
345
346                 attr = (cmd_provider_attr_str_t *) new(std::nothrow) char[msg.size()];
347                 retm_if(!attr, "Failed to allocate memory");
348
349                 msg.disclose((char *)attr, msg.size());
350
351                 if (m_attribute_str_cb)
352                         m_attribute_str_cb(this, attr->attribute, attr->value, attr->len, m_attribute_str_user_data);
353
354                 delete [] attr;
355                 break;
356         }
357 }
358
359 bool sensor_provider::send(ipc::message &msg)
360 {
361         AUTOLOCK(m_cmutex);
362         if (!m_socket) {
363                 _E("Socket is not connected");
364                 return false;
365         }
366
367         retvm_if(msg.size() >= MAX_MSG_CAPACITY, true, "Invaild message size[%u]", msg.size());
368
369         ssize_t size = 0;
370         char *buf = msg.body();
371
372         /* header */
373         size = m_socket->send(reinterpret_cast<void *>(msg.header()),
374             sizeof(ipc::message_header), true);
375         retvm_if(size <= 0, false, "Failed to send header");
376
377         /* if body size is zero, skip to send body message */
378         retv_if(msg.size() == 0, true);
379
380         /* body */
381         size = m_socket->send(buf, msg.size(), true);
382         retvm_if(size <= 0, false, "Failed to send body");
383
384         return true;
385 }