Update registered device list to plugin with payload information
[platform/core/connectivity/ua-manager.git] / ua-daemon / src / ua-manager-core.c
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License")
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <time.h>
19
20 #include "ua-api.h"
21 #include "ua-plugin.h"
22 #include "ua-internal.h"
23 #include "ua-manager-common.h"
24 #include "ua-plugin-manager.h"
25
26 #include "ua-manager-database.h"
27 #include "ua-cloud-plugin-handler.h"
28
29 #include "ua-vendor-plugin-manager.h"
30
31 #define UAM_MAX_USERS 255
32 #define USER_ACCOUNT_DEFAULT "default@default.com"
33 #define USER_NAME_DEFAULT "default"
34
35 typedef struct {
36         char *name;
37         unsigned int sensors;
38         uam_pm_detection_mode_e mode;
39         uam_db_service_info_t *service;
40 } uam_monitor_info_t;
41
42 typedef struct {
43         char *name;
44         unsigned int sensors;
45         guint timer;
46 } uam_scanner_info_t;
47
48 static GSList *users; /* List of users - uam_db_user_info_t */
49 static GSList *devices; /* List of devices - uam_db_device_info_t */
50 static GSList *services; /* List of services -  uam_db_service_info_t */
51 static GSList *svc_devs; /* List of service device mapping -  uam_svc_dev_info_t */
52 static GSList *payloads; /* List of payloads - uam_db_payload_info_t */
53
54 static GSList *monitors; /* List of monitoring apps - uam_monitor_info_t */
55 static GSList *scanners; /* List of scanning apps -  uam_scanner_info_t */
56
57 static guint detection_timer = 0;
58 static unsigned int detection_window;
59
60 static unsigned int detecting_sensors = 0;
61
62 static gint __compare_user_account(gconstpointer data, gconstpointer user_data)
63 {
64         const uam_db_user_info_t *user = data;
65         const char *account = user_data;
66
67         retv_if(NULL == user, -1);
68         retv_if(NULL == user->account, -1);
69         retv_if(NULL == account, -1);
70
71         return g_strcmp0(user->account, account);
72 }
73
74 static gint __compare_user_id(gconstpointer data, gconstpointer user_data)
75 {
76         const uam_db_user_info_t *user = data;
77         const int *id = user_data;
78
79         UAM_INFO("[%d][%d]", *id, user->user_id);
80
81         retv_if(NULL == user, -1);
82         retv_if(NULL == user->account, -1);
83         retv_if(NULL == id, -1);
84
85         if (*id != user->user_id)
86                 return 1;
87
88         return 0;
89 }
90
91 static gint __compare_svc_name(gconstpointer data, gconstpointer user_data)
92 {
93         const uam_db_service_info_t *service = data;
94         const char *svc_name = user_data;
95
96         retv_if(NULL == service, -1);
97         retv_if(NULL == service->name, -1);
98         retv_if(NULL == svc_name, -1);
99
100         return g_strcmp0(service->name, svc_name);
101 }
102
103 static gint __compare_payload(gconstpointer data, gconstpointer user_data)
104 {
105         const uam_db_payload_info_t *db_payload = data;
106         const uam_ble_payload_s *payload = user_data;
107
108         retv_if(NULL == db_payload, -1);
109         retv_if(NULL == payload, -1);
110
111         if ((db_payload->primary_key == payload->primary_key) &&
112                 (0 == g_strcmp0(db_payload->device_uid, payload->device_uid)))
113                 return 0;
114         return -1;
115 }
116
117 static gint __compare_db_payload(gconstpointer data, gconstpointer user_data)
118 {
119         const uam_db_payload_info_t *db_payload = data;
120         const uam_ble_payload_s *payload = user_data;
121
122         retv_if(NULL == db_payload, -1);
123         retv_if(NULL == payload, -1);
124
125         if ((db_payload->primary_key == payload->primary_key) &&
126                 (0 == g_strcmp0(db_payload->device_uid, payload->device_uid)))
127                 return 0;
128         return -1;
129 }
130
131 static void __free_address_info(gpointer data)
132 {
133         FUNC_ENTRY;
134         uam_db_address_info_t *addr = data;
135
136         ret_if(NULL == addr);
137
138         g_free(addr->address);
139         g_free(addr);
140
141         FUNC_EXIT;
142 }
143
144 static void __free_dev_tech_info(gpointer data)
145 {
146         FUNC_ENTRY;
147         uam_db_tech_info_t *tech_info = data;
148         GSList *l;
149
150         ret_if(NULL == tech_info);
151
152         /* Delete the tech information from the service list that includes tech. */
153         for (l = tech_info->svc_list; NULL != l; l = g_slist_next(l)) {
154                 uam_db_service_info_t *svc_info = l->data;
155
156                 if (!svc_info || !svc_info->dev_techs)
157                         continue;
158
159                 svc_info->dev_techs = g_slist_remove(svc_info->dev_techs, tech_info);
160         }
161
162         g_slist_free_full(tech_info->addresses, __free_address_info);
163         tech_info->addresses = NULL;
164
165         g_free(tech_info);
166
167         FUNC_EXIT;
168 }
169
170 static void __free_user_device(gpointer data)
171 {
172         FUNC_ENTRY;
173         uam_db_device_info_t *device = data;
174
175         ret_if(NULL == device);
176
177         /* Remove device data from global device list */
178         devices = g_slist_remove(devices, device);
179
180         /* Free allocated memory */
181         g_free(device->device_id);
182         g_slist_free_full(device->tech_list, __free_dev_tech_info);
183         g_free(device);
184
185         FUNC_EXIT;
186 }
187
188 static void __send_device_event(int err, int event, const uam_device_info_s *dev_info)
189 {
190         FUNC_ENTRY;
191         GVariant *param;
192
193         UAM_INFO_C("Send %s to applications", _uam_manager_event_to_str(event));
194         /* Send device event to application */
195         param = g_variant_new("(iiisss)",
196                         err,
197                         dev_info->operating_system,
198                         dev_info->type,
199                         dev_info->mac,
200                         dev_info->ipv4_addr,
201                         dev_info->device_id);
202         if (UAM_ERROR_NONE != _uam_manager_send_event(NULL, event, param))
203                 UAM_ERR("Failed to send %s", _uam_manager_event_to_str(event));
204
205         FUNC_EXIT;
206 }
207
208 static void __print_service(gpointer data, gpointer user_data)
209 {
210         FUNC_ENTRY;
211         uam_db_service_info_t *service = data;
212         uam_db_tech_info_t *tech = user_data;
213
214         ret_if(NULL == tech);
215         ret_if(NULL == service);
216
217         UAM_DBG("DevId: %s, Type: %d, Svc: %s, Cycle: %d",
218                         tech->device->device_id, tech->tech_type,
219                         service->name, service->cycle);
220
221         FUNC_EXIT;
222 }
223
224 static void __print_svc_dev(gpointer data, gpointer user_data)
225 {
226         FUNC_ENTRY;
227         uam_svc_dev_info_t *svc_dev = data;
228
229         ret_if(NULL == svc_dev);
230
231         UAM_DBG("DevId: %s, Svc: %s, payload primary key: %d",
232                         svc_dev->device_id, svc_dev->service,
233                         svc_dev->payload->primary_key);
234
235         FUNC_EXIT;
236 }
237
238 static void __add_service_to_dev_tech_mapping(
239                 uam_db_tech_info_t *tech, uam_db_service_info_t *service)
240 {
241         FUNC_ENTRY;
242
243         ret_if(NULL == tech);
244         ret_if(NULL == service);
245
246         tech->svc_list = g_slist_append(tech->svc_list, service);
247         service->dev_techs = g_slist_append(service->dev_techs, tech);
248         g_slist_foreach(tech->svc_list, __print_service, tech);
249
250         FUNC_EXIT;
251 }
252
253 static void __remove_service_to_dev_tech_mapping(
254                 uam_db_tech_info_t *tech, uam_db_service_info_t *service)
255 {
256         FUNC_ENTRY;
257
258         ret_if(NULL == tech);
259         ret_if(NULL == service);
260
261         tech->svc_list = g_slist_remove(tech->svc_list, service);
262         service->dev_techs = g_slist_remove(service->dev_techs, tech);
263         g_slist_foreach(tech->svc_list, __print_service, tech);
264
265         FUNC_EXIT;
266 }
267
268 static char *__get_mac_addr(uam_db_tech_info_t *tech)
269 {
270         FUNC_ENTRY;
271         GSList *l;
272
273         retv_if(NULL == tech, NULL);
274
275         for (l = tech->addresses; NULL != l; l = g_slist_next(l)) {
276                 uam_db_address_info_t *addr = l->data;
277
278                 if (!addr)
279                         continue;
280
281                 if (addr->addr_type == UAM_ADDR_TYPE_BT ||
282                                 addr->addr_type == UAM_ADDR_TYPE_BLE ||
283                                 addr->addr_type == UAM_ADDR_TYPE_WIFI ||
284                                 addr->addr_type == UAM_ADDR_TYPE_P2P)
285                         return addr->address;
286         }
287
288         FUNC_EXIT;
289         return NULL;
290 }
291
292 static void __uam_core_copy_addr(uam_device_info_s *device, uam_db_address_info_t *addr)
293 {
294         switch (addr->addr_type) {
295         case UAM_ADDR_TYPE_BLE:
296         case UAM_ADDR_TYPE_BT:
297         case UAM_ADDR_TYPE_P2P:
298         case UAM_ADDR_TYPE_WIFI:
299                 g_strlcpy(device->mac, addr->address,
300                                 UAM_MAC_ADDRESS_STRING_LEN);
301                 break;
302         case UAM_ADDR_TYPE_IPv4:
303                 g_strlcpy(device->ipv4_addr,
304                                 addr->address,
305                                 UAM_IP_ADDRESS_MAX_STRING_LEN);
306                 break;
307         default:
308                 UAM_WARN("Unknown address type %d", addr->addr_type);
309         }
310 }
311
312 static int __copy_tech_info_to_device_info(uam_db_tech_info_t *tech, uam_device_info_s *device)
313 {
314         FUNC_ENTRY;
315         GSList *l;
316
317         retv_if(NULL == tech, UAM_ERROR_INVALID_PARAMETER);
318
319         memset(device, 0x00, sizeof(uam_device_info_s));
320         for (l = tech->addresses; NULL != l; l = g_slist_next(l)) {
321                 uam_db_address_info_t *addr = l->data;
322
323                 if (!addr)
324                         continue;
325
326                 __uam_core_copy_addr(device, addr);
327         }
328
329         device->operating_system = tech->device->os;
330         g_strlcpy(device->device_id, tech->device->device_id,
331                 UAM_DEVICE_ID_MAX_STRING_LEN);
332         device->type = tech->tech_type;
333         device->discriminant = tech->discriminant;
334         device->last_seen = tech->last_seen;
335
336         FUNC_EXIT;
337         return UAM_ERROR_NONE;
338 }
339
340 static int _uam_remove_user_device(uam_db_device_info_t *device)
341 {
342         FUNC_ENTRY;
343         uam_device_info_s dev_info;
344         int user_id;
345         GSList *l;
346         int ret = UAM_ERROR_NONE;
347
348         retv_if(NULL == device, UAM_ERROR_INVALID_PARAMETER);
349         user_id = device->user->user_id;
350
351         retv_if(UAM_ERROR_NONE != __uam_db_begin_transaction(), UAM_ERROR_DB_FAILED);
352         for (l = device->tech_list; NULL != l; l = g_slist_next(l)) {
353                 uam_db_tech_info_t *tech = l->data;
354
355                 if (!tech)
356                         continue;
357
358                 /* Copy tech info to device info */
359                 ret = __copy_tech_info_to_device_info(tech, &dev_info);
360                 if (UAM_ERROR_NONE != ret) {
361                         UAM_ERR("__copy_tech_info_to_device_info failed");
362                         __uam_db_end_transaction(0);
363                         return ret;
364                 }
365
366                 /* Unregister device from plugin */
367                 ret = _uam_pm_unregister_device(user_id, &dev_info);
368                 if (UAM_ERROR_NONE != ret)
369                         UAM_ERR("_uam_pm_unregister_device failed with %s",
370                                         _uam_manager_error_to_str(ret));
371
372                 /* Send device removed event to application */
373                 __send_device_event(UAM_ERROR_NONE, UAM_EVENT_DEVICE_REMOVED, &dev_info);
374
375                 /* Remove device from database */
376                 ret = _uam_device_db_delete_device_info(
377                                         dev_info.device_id, dev_info.type, dev_info.mac);
378                 if (UAM_ERROR_NONE != ret) {
379                         UAM_ERR("_uam_device_db_delete_device_info failed");
380                         __uam_db_end_transaction(0);
381                         return ret;
382                 }
383         }
384         __uam_db_end_transaction(1);
385
386         FUNC_EXIT;
387         return ret;
388 }
389
390 static int __free_uam_db_user_info(gpointer data)
391 {
392         FUNC_ENTRY;
393         uam_db_user_info_t *user = data;
394         GSList *l;
395         int ret = UAM_ERROR_NONE;
396
397         for (l = user->devices; NULL != l; l = g_slist_next(l)) {
398                 uam_db_device_info_t *device = l->data;
399                 ret = _uam_remove_user_device(device);
400                 if (UAM_ERROR_NONE != ret) {
401                         UAM_ERR("_uam_remove_user_device failed");
402                         return ret;
403                 }
404         }
405
406         g_slist_free_full(user->devices, __free_user_device);
407
408         /* Set/update registered device list to plugins */
409         if (UAM_ERROR_NONE != _uam_pm_set_registered_devices(devices))
410                 UAM_ERR("_uam_pm_set_registered_devices failed");
411
412         /* Set/update registered device list to cloud plugin */
413         _uam_cloud_update_registered_devices();
414
415         g_free(user->name);
416         g_free(user->account);
417         g_free(user);
418
419         FUNC_EXIT;
420         return ret;
421 }
422
423 static gint __compare_device_id(gconstpointer data, gconstpointer user_data)
424 {
425         FUNC_ENTRY;
426         const uam_db_device_info_t *device = data;
427         const char *dev_id = user_data;
428
429         retv_if(NULL == device, -1);
430         retv_if(NULL == device->device_id, -1);
431         retv_if(NULL == dev_id, -1);
432
433         FUNC_EXIT;
434         return g_strcmp0(device->device_id, dev_id);
435 }
436
437 static gint __compare_tech_type(gconstpointer data, gconstpointer user_data)
438 {
439         FUNC_ENTRY;
440         const uam_db_tech_info_t *tech = data;
441         const int *type = user_data;
442
443         retv_if(NULL == tech, -1);
444         retv_if(NULL == type, -1);
445
446         FUNC_EXIT;
447         return ((*type == tech->tech_type) ? 0 : 1);
448 }
449
450 static uam_db_tech_info_t *__get_tech_info_by_mac(const char *mac)
451 {
452         FUNC_ENTRY;
453         GSList *l;
454
455         for (l = devices; NULL != l; l = g_slist_next(l)) {
456                 uam_db_device_info_t *dev = l->data;
457                 GSList *l1;
458
459                 if (!dev)
460                         continue;
461
462                 for (l1 = dev->tech_list; NULL != l1; l1 = g_slist_next(l1)) {
463                         uam_db_tech_info_t *tech = l1->data;
464                         GSList *l2;
465
466                         if (!tech)
467                                 continue;
468
469                         for (l2 = tech->addresses; NULL != l2; l2 = g_slist_next(l2)) {
470                                 uam_db_address_info_t *addr = l2->data;
471
472                                 if (!addr)
473                                         continue;
474
475                                 if (UAM_ADDR_TYPE_BLE == addr->addr_type ||
476                                                 UAM_ADDR_TYPE_BT == addr->addr_type ||
477                                                 UAM_ADDR_TYPE_P2P == addr->addr_type ||
478                                                 UAM_ADDR_TYPE_WIFI == addr->addr_type)
479                                         if (!strcasecmp(addr->address, mac)) {
480                                                 UAM_DBG("Device found Mac: %s, type: %d",
481                                                                 addr->address, addr->addr_type);
482                                                 return tech;
483                                         }
484                         }
485                 }
486         }
487
488         FUNC_EXIT;
489         return NULL;
490 }
491
492 static int __get_uam_db_dev_list_to_uam_dev_list(
493                 GSList *db_dev_list, uam_device_info_s **device_list, int *count)
494 {
495         FUNC_ENTRY;
496         GSList *l;
497         int indx = 0;
498         int ret = UAM_ERROR_NONE;
499
500         *count = 0;
501         /* Calculate num devices first */
502         for (l = db_dev_list; NULL != l; l = g_slist_next(l)) {
503                 uam_db_device_info_t *db_info = l->data;
504                 GSList *l1;
505
506                 if (!db_info || !db_info->device_id)
507                         continue;
508
509                 for (l1 = db_info->tech_list; NULL != l1; l1 = g_slist_next(l1)) {
510                         uam_db_tech_info_t *tech = l1->data;
511
512                         if (!tech || !tech->addresses)
513                                 continue;
514
515                         (*count)++;
516                 }
517         }
518         UAM_INFO("Count = %d", *count);
519
520         *device_list = g_new0(uam_device_info_s, *count);
521
522         /* Copy devices */
523         for (l = db_dev_list; NULL != l; l = g_slist_next(l)) {
524                 uam_db_device_info_t *db_info = l->data;
525                 GSList *l1;
526
527                 if (!db_info || !db_info->device_id)
528                         continue;
529
530                 for (l1 = db_info->tech_list; NULL != l1; l1 = g_slist_next(l1)) {
531                         uam_db_tech_info_t *tech = l1->data;
532
533                         if (!tech || !tech->addresses)
534                                 continue;
535
536                         /* Copy tech info to device info */
537                         ret = __copy_tech_info_to_device_info(tech, &((*device_list)[indx]));
538                         if (UAM_ERROR_NONE != ret) {
539                                 UAM_ERR("__copy_tech_info_to_device_info failed");
540                                 return ret;
541                         }
542                         indx++;
543                 }
544         }
545
546         UAM_INFO("Count = %d, indx = %d", *count, indx);
547         FUNC_EXIT;
548         return ret;
549 }
550
551 static uam_monitor_info_t *__uam_find_monitor(GSList *monitor_list,
552                 const char *name, const char *svc_name, uam_pm_detection_mode_e mode)
553 {
554 //      FUNC_ENTRY;
555         GSList *l;
556
557         retv_if(NULL == name, NULL);
558         retv_if(NULL == monitor_list, NULL);
559
560         for (l = monitor_list; NULL != l; l = g_slist_next(l)) {
561                 uam_monitor_info_t *monitor = l->data;
562
563                 if (!monitor || !monitor->name ||
564                                 !monitor->service || !monitor->service->name)
565                         continue;
566
567                 if ((mode == monitor->mode) &&
568                                 (0 == g_strcmp0(monitor->name, name)) &&
569                                 (0 == g_strcmp0(monitor->service->name, svc_name))) {
570                         UAM_DBG("Monitoring application found in list");
571                         return monitor;
572                 }
573         }
574
575 //      FUNC_EXIT;
576         return NULL;
577 }
578
579 unsigned int _uam_core_get_active_sensors(int detection_mode)
580 {
581         FUNC_ENTRY;
582         unsigned int sensors = 0;
583         GSList *l;
584
585         retv_if((UAM_DETECT_PRESENCE != detection_mode) &&
586                         (UAM_DETECT_ABSENCE != detection_mode), 0);
587
588         for (l = monitors; NULL != l; l = g_slist_next(l)) {
589                 uam_monitor_info_t *monitor = l->data;
590
591                 if (!monitor || !monitor->name || (detection_mode != monitor->mode))
592                         continue;
593
594                 sensors |= monitor->sensors;
595         }
596
597         FUNC_EXIT;
598         return sensors;
599 }
600
601 unsigned int _uam_core_get_env_sensors()
602 {
603         FUNC_ENTRY;
604         unsigned int sensors = 0;
605
606         sensors |= UAM_SENSOR_BITMASK_MOTION;
607         sensors |= UAM_SENSOR_BITMASK_LIGHT;
608
609         FUNC_EXIT;
610         return sensors;
611 }
612
613 unsigned int _uam_core_get_active_env_sensors(int detection_mode)
614 {
615         FUNC_ENTRY;
616         unsigned int sensors = 0;
617         GSList *l;
618
619         retv_if((UAM_DETECT_PRESENCE != detection_mode) &&
620                         (UAM_DETECT_ABSENCE != detection_mode), 0);
621
622         for (l = monitors; NULL != l; l = g_slist_next(l)) {
623                 uam_monitor_info_t *monitor = l->data;
624
625                 if (!monitor || !monitor->name || (detection_mode != monitor->mode))
626                         continue;
627
628                 sensors |= monitor->sensors & _uam_core_get_env_sensors();
629         }
630
631         FUNC_EXIT;
632         return sensors;
633 }
634
635 static GSList *__convert_db_svc_list_to_uam_svc_list(GSList *db_svc_list)
636 {
637         FUNC_ENTRY;
638         GSList *l;
639         GSList *svc_list = NULL;
640
641         retv_if(NULL == db_svc_list, NULL);
642
643         /*
644          * Iterate over the db_svc_list and add each service to the global
645          * service list "services" if its not already inserted. Also append this
646          * uam_db_service_info_t to svc_list.
647          */
648         for (l = db_svc_list; NULL != l; l = g_slist_next(l)) {
649                 db_service_info_t *db_svc = l->data;
650                 uam_db_service_info_t *service;
651                 GSList *l1;
652
653                 if (!db_svc)
654                         continue;
655
656                 l1 = g_slist_find_custom(services,
657                                 db_svc->service_name, __compare_svc_name);
658                 if (!l1) {
659                         service = g_new0(uam_db_service_info_t, 1);
660                         service->name = g_strdup(db_svc->service_name);
661                         service->cycle = db_svc->cycle;
662                         services = g_slist_append(services, service);
663                 } else
664                         service = l1->data;
665
666                 svc_list = g_slist_append(svc_list, service);
667         }
668
669         FUNC_EXIT;
670         return svc_list;
671 }
672
673 static void __uam_copy_db_payload_info(uam_ble_payload_s *dst_payload,
674         uam_db_payload_info_t *src_payload)
675 {
676         if (src_payload) {
677                 dst_payload->primary_key = src_payload->primary_key;
678                 dst_payload->device_icon = src_payload->device_icon;
679                 dst_payload->secondary_key = src_payload->secondary_key;
680                 if (src_payload->device_uid)
681                         memcpy(dst_payload->device_uid,
682                         src_payload->device_uid, UAM_BLE_PAYLOAD_DEVICE_UID_LEN);
683                 if (src_payload->bt_mac)
684                         memcpy(dst_payload->bt_mac,
685                         src_payload->bt_mac, UAM_BT_MAC_ADDRESS_STRING_LEN);
686         }
687 }
688
689 static void __uam_copy_uam_payload_info(
690                 uam_db_payload_info_t *dst_payload, uam_ble_payload_s *src_payload)
691 {
692         if (src_payload) {
693                 dst_payload->primary_key = src_payload->primary_key;
694                 dst_payload->device_icon = src_payload->device_icon;
695                 dst_payload->secondary_key = src_payload->secondary_key;
696                 dst_payload->device_uid = g_memdup(&(src_payload->device_uid),
697                                         UAM_BLE_PAYLOAD_DEVICE_UID_LEN);
698                 dst_payload->bt_mac = g_memdup(&(src_payload->bt_mac),
699                                         UAM_BT_MAC_ADDRESS_STRING_LEN);
700         }
701 }
702
703 static GSList *_uam_core_find_svc_dev_list(uam_device_info_s *dev_info)
704 {
705         FUNC_ENTRY;
706         uam_svc_dev_info_t *svc_dev = NULL;
707         GSList *l;
708         GSList *svc_dev_list = NULL;
709
710         retv_if(NULL == dev_info, NULL);
711
712         /*
713          * Iterate over the svc_devs and find each service device information
714          */
715         for (l = svc_devs; NULL != l; l = g_slist_next(l)) {
716                 svc_dev = l->data;
717
718                 if (!svc_dev || !svc_dev->device_id || !svc_dev->service)
719                         continue;
720
721                 if ((0 == g_strcmp0(svc_dev->device_id, dev_info->device_id)) &&
722                                 (svc_dev->tech_type == dev_info->type)) {
723                         svc_dev_list = g_slist_append(svc_dev_list, svc_dev);
724                         UAM_DBG("Service found for device in list");
725                 }
726         }
727
728         FUNC_EXIT;
729         return svc_dev_list;
730 }
731
732 static void __uam_core_add_dev_to_list(
733                 uam_db_user_info_t *user, const uam_device_info_s *dev_info,
734                 int presence_state, unsigned long long last_seen, GSList *svc_list,
735                 GSList *svc_dev_list)
736 {
737         FUNC_ENTRY;
738         uam_db_tech_info_t *tech;
739         uam_db_device_info_t *device;
740         GSList *l;
741
742         ret_if(NULL == dev_info);
743         ret_if(NULL == user);
744
745         l = g_slist_find_custom(devices, dev_info->device_id, __compare_device_id);
746         if (NULL != l) {
747                 device = l->data;
748                 ret_if(user != device->user);
749                 ret_if(device->supported_techs & dev_info->type);
750
751                 if (device->os != dev_info->operating_system) {
752                         UAM_INFO("device->os: %d, dev_info->operating_system: %d",
753                                         device->os, dev_info->operating_system);
754                         /* Update device OS type */
755                         if (UAM_OS_TYPE_INVALID == device->os || UAM_OS_TYPE_UNDEFINED == device->os)
756                                 device->os = dev_info->operating_system;
757                         else
758                                 UAM_WARN("Strange - OS types did not match, need to check");
759                 }
760         } else {
761                 device = g_new0(uam_db_device_info_t, 1);
762                 device->device_id = g_strdup(dev_info->device_id);
763                 device->os = dev_info->operating_system;
764                 device->discriminant = dev_info->discriminant;
765                 device->user = user;
766
767                 /* Add device to global device list */
768                 devices = g_slist_append(devices, device);
769
770                 /* Add same device to user's device list */
771                 user->devices = g_slist_append(user->devices, device);
772         }
773
774         tech = g_new0(uam_db_tech_info_t, 1);
775         tech->tech_type = dev_info->type;
776         tech->presence_state = presence_state;
777         tech->last_seen = last_seen;
778         tech->device = device;
779         tech->discriminant = dev_info->discriminant;
780
781         tech->svc_list = svc_list;
782         g_slist_foreach(tech->svc_list, __print_service, tech);
783         for (l = svc_list; NULL != l; l = g_slist_next(l)) {
784                 uam_db_service_info_t *service = l->data;
785
786                 if (!service)
787                         continue;
788
789                 service->dev_techs = g_slist_prepend(service->dev_techs, tech);
790         }
791         tech->svc_dev_list = svc_dev_list;
792         g_slist_foreach(tech->svc_dev_list, __print_svc_dev, NULL);
793
794         /* Add tech info to tech list */
795         device->tech_list = g_slist_append(device->tech_list, tech);
796         device->supported_techs |= tech->tech_type;
797         UAM_INFO("device->supported_techs: %8.8X", device->supported_techs);
798
799         if (0 < strlen(dev_info->mac)) {
800                 uam_db_address_info_t *addr;
801
802                 addr = g_new0(uam_db_address_info_t, 1);
803                 addr->address = g_strdup(dev_info->mac);
804
805                 switch (dev_info->type) {
806                 case UAM_TECH_TYPE_BLE:
807                         addr->addr_type = UAM_ADDR_TYPE_BLE;
808                         break;
809                 case UAM_TECH_TYPE_BT:
810                         addr->addr_type = UAM_ADDR_TYPE_BT;
811                         break;
812                 case UAM_TECH_TYPE_P2P:
813                         addr->addr_type = UAM_ADDR_TYPE_P2P;
814                         break;
815                 case UAM_TECH_TYPE_WIFI:
816                         addr->addr_type = UAM_ADDR_TYPE_WIFI;
817                         break;
818                 default:
819                         UAM_ERR("Unknown tech type: %d", dev_info->type);
820                         g_free(addr->address);
821                         g_free(addr);
822                         addr = NULL;
823                 }
824
825                 if (addr) {
826                         UAM_DBG("MAC address %s added for tech type: %d",
827                                         dev_info->mac, dev_info->type);
828                         tech->addresses = g_slist_append(tech->addresses, addr);
829                 }
830         }
831
832         if (0 < strlen(dev_info->ipv4_addr)) {
833                 uam_db_address_info_t *addr;
834
835                 if (UAM_TECH_TYPE_BLE == dev_info->type ||
836                                 UAM_TECH_TYPE_BT == dev_info->type)
837                         UAM_WARN("IPv4 address %s added for tech type: %d",
838                                         dev_info->ipv4_addr, dev_info->type);
839                 else
840                         UAM_DBG("IPv4 address %s added for tech type: %d",
841                                         dev_info->ipv4_addr, dev_info->type);
842
843                 addr = g_new0(uam_db_address_info_t, 1);
844                 addr->addr_type = UAM_ADDR_TYPE_IPv4;
845                 addr->address = g_strdup(dev_info->ipv4_addr);
846
847                 tech->addresses = g_slist_append(tech->addresses, addr);
848         }
849
850         FUNC_EXIT;
851 }
852
853 int _uam_core_add_user(int *user_id, const char *account, const char *name)
854 {
855         FUNC_ENTRY;
856         GSList *l;
857         uam_db_user_info_t *user;
858         int ret = UAM_ERROR_NONE;
859
860         l = g_slist_find_custom(users, account, __compare_user_account);
861         retv_if((NULL != l) && (l->data != NULL), UAM_ERROR_ALREADY_REGISTERED);
862
863         user = g_new0(uam_db_user_info_t, 1);
864
865         /* Add user to database */
866         ret = _uam_db_insert_user_info(&(user->user_id), name, account);
867         if (UAM_ERROR_NONE != ret) {
868                 UAM_ERR("_uam_db_insert_user_info failed [%d]", ret);
869                 g_free(user);
870                 return ret;
871         }
872
873         user->name = g_strdup(name);
874         user->account = g_strdup(account);
875         user->devices = NULL;
876
877         *user_id = user->user_id;
878
879         users = g_slist_append(users, user);
880
881         /* Send user added event to application */
882         if (UAM_ERROR_NONE != _uam_manager_send_event(NULL,
883                                 UAM_EVENT_USER_ADDED, g_variant_new("(iss)",
884                                         UAM_ERROR_NONE, user->account, user->name)))
885                 UAM_ERR("Failed to send UAM_EVENT_USER_ADDED");
886
887         FUNC_EXIT;
888         return UAM_ERROR_NONE;
889 }
890
891 int _uam_core_remove_user(const char *account)
892 {
893         FUNC_ENTRY;
894         GSList *l;
895         uam_db_user_info_t *user;
896         int ret = UAM_ERROR_NONE;
897
898         l = g_slist_find_custom(users, account, __compare_user_account);
899         retv_if((NULL == l), UAM_ERROR_NOT_REGISTERED);
900         user = l->data;
901
902         /* Remove user from database */
903         ret = _uam_db_delete_by_user_id(user->user_id);
904         if (UAM_ERROR_NONE != ret) {
905                 UAM_ERR("_uam_db_delete_by_user_id failed");
906                 return ret;
907         }
908
909         users = g_slist_remove(users, user);
910
911         /* Send user removed event to application */
912         if (UAM_ERROR_NONE != _uam_manager_send_event(NULL,
913                                 UAM_EVENT_USER_REMOVED, g_variant_new("(iss)",
914                                         UAM_ERROR_NONE, user->account, user->name)))
915                 UAM_ERR("Failed to send UAM_EVENT_USER_REMOVED");
916
917         ret = __free_uam_db_user_info((gpointer)user);
918         if (UAM_ERROR_NONE != ret)
919                 UAM_WARN("_free_uam_db_user_info failed");
920
921         FUNC_EXIT;
922         return UAM_ERROR_NONE;
923 }
924
925 int _uam_core_update_user(uam_user_info_s *user)
926 {
927         FUNC_ENTRY;
928         GSList *l;
929         uam_db_user_info_t *user_info;
930
931         retv_if(NULL == user, UAM_ERROR_INVALID_PARAMETER);
932
933         /* Retrieve user from list */
934         l = g_slist_find_custom(users, user->account, __compare_user_account);
935         retv_if((NULL == l) || (l->data == NULL), UAM_ERROR_NOT_REGISTERED);
936
937         user_info = l->data;
938         g_strlcpy(user_info->name, user->name, UAM_USER_NAME_MAX_STRING_LEN);
939
940         /* Update user to database */
941         if (UAM_ERROR_NONE != _uam_db_update_user_info(user_info)) {
942                 UAM_ERR("_uam_db_update_user_info failed");
943                 return UAM_ERROR_DB_FAILED;
944         }
945
946         FUNC_EXIT;
947         return UAM_ERROR_NONE;
948 }
949
950 int _uam_core_add_device(const char *account, const uam_device_info_s *dev_info)
951 {
952         FUNC_ENTRY;
953         int ret;
954         GSList *l;
955         uam_db_device_info_t *device;
956         uam_db_user_info_t *user;
957
958         retv_if(NULL == account, UAM_ERROR_INVALID_PARAMETER);
959         retv_if(NULL == dev_info, UAM_ERROR_INVALID_PARAMETER);
960
961         l = g_slist_find_custom(users, account, __compare_user_account);
962         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
963         user = l->data;
964
965         l = g_slist_find_custom(devices, dev_info->device_id, __compare_device_id);
966         if (NULL != l) {
967                 device = l->data;
968                 retv_if(user != device->user, UAM_ERROR_ALREADY_REGISTERED);
969                 retv_if((dev_info->type & device->supported_techs),
970                                 UAM_ERROR_ALREADY_REGISTERED);
971         }
972
973         UAM_INFO("[%d]", user->user_id);
974
975         ret = _uam_pm_register_device(user->user_id, dev_info);
976         if (UAM_ERROR_NONE != ret) {
977                 UAM_ERR("_uam_pm_register_device failed with %s",
978                                 _uam_manager_error_to_str(ret));
979                 return ret;
980         }
981
982         FUNC_EXIT;
983         return UAM_ERROR_NONE;
984 }
985
986 int _uam_core_is_device_added(uam_device_info_s *dev, gboolean *is_added)
987 {
988         FUNC_ENTRY;
989         uam_db_device_info_t *device;
990         GSList *l;
991
992         retv_if(NULL == dev, UAM_ERROR_INVALID_PARAMETER);
993         retv_if(NULL == is_added, UAM_ERROR_INVALID_PARAMETER);
994
995         *is_added = FALSE;
996         l = g_slist_find_custom(devices, dev->device_id, __compare_device_id);
997         if (NULL == l)
998                 goto done;
999
1000         device = l->data;
1001         if (!(device->supported_techs & dev->type))
1002                 goto done;
1003
1004         for (l = device->tech_list; NULL != l; l = g_slist_next(l)) {
1005                 uam_db_tech_info_t *tech = l->data;
1006                 GSList *l1;
1007
1008                 if (!tech)
1009                         continue;
1010
1011                 if (dev->type != tech->tech_type)
1012                         continue;
1013
1014                 for (l1 = tech->addresses; NULL != l1; l1 = g_slist_next(l1)) {
1015                         uam_db_address_info_t *addr = l1->data;
1016
1017                         if (!addr)
1018                                 continue;
1019
1020                         if (UAM_ADDR_TYPE_BLE == addr->addr_type ||
1021                                         UAM_ADDR_TYPE_BT == addr->addr_type ||
1022                                         UAM_ADDR_TYPE_P2P == addr->addr_type ||
1023                                         UAM_ADDR_TYPE_WIFI == addr->addr_type)
1024                                 if (!strcasecmp(addr->address, dev->mac)) {
1025                                         *is_added = TRUE;
1026                                         break;
1027                                 }
1028                 }
1029                 break;
1030         }
1031
1032 done:
1033         UAM_INFO("Device %s", (*is_added ? "Added" : "Not Added"));
1034         FUNC_EXIT;
1035         return UAM_ERROR_NONE;
1036 }
1037
1038 static int __uam_remove_device(int user_id, uam_db_device_info_t *device,
1039         const uam_device_info_s *dev_info, uam_db_tech_info_t *tech)
1040 {
1041         int ret;
1042         GSList *l;
1043         int count = 0;
1044
1045         ret = _uam_db_get_device_services_count(dev_info->device_id,
1046                                 dev_info->type, dev_info->mac, &count);
1047         if (UAM_ERROR_NONE != ret) {
1048                 UAM_ERR("_uam_db_get_device_services_count failed with %s",
1049                                 _uam_manager_error_to_str(ret));
1050                 return ret;
1051         }
1052
1053         if (1 < count) {
1054                 ret = UAM_ERROR_RESOURCE_BUSY;
1055                 UAM_WARN("other service uses this device ref:[%d]", count);
1056                 return ret;
1057         }
1058
1059         ret = _uam_pm_unregister_device(user_id, dev_info);
1060         if (UAM_ERROR_NONE != ret) {
1061                 UAM_ERR("_uam_pm_unregister_device failed with %s",
1062                                 _uam_manager_error_to_str(ret));
1063                 return ret;
1064         }
1065
1066         /* Send device removed event to application */
1067         __send_device_event(ret, UAM_EVENT_DEVICE_REMOVED, dev_info);
1068
1069         retv_if(UAM_ERROR_NONE != __uam_db_begin_transaction(), UAM_ERROR_DB_FAILED);
1070         /* Remove device from database */
1071         ret = _uam_device_db_delete_device_info(
1072                                 dev_info->device_id, dev_info->type, dev_info->mac);
1073         if (UAM_ERROR_NONE != ret) {
1074                 UAM_ERR("_uam_device_db_delete_device_info failed");
1075                 __uam_db_end_transaction(0);
1076                 return ret;
1077         }
1078
1079         /* Remove device from service */
1080         for (l = tech->svc_list; l; l = g_slist_next(l)) {
1081                 uam_db_service_info_t *svc = l->data;
1082
1083                 if (!svc || !svc->name)
1084                         continue;
1085                 ret = _uam_core_service_remove_device(svc->name,
1086                                 dev_info->device_id, dev_info->type);
1087                 if (UAM_ERROR_NONE != ret)
1088                         UAM_ERR("_uam_device_db_delete_device_info failed");
1089         }
1090         __uam_db_end_transaction(1);
1091
1092         /* Remove tech info from device's tech list */
1093         device->tech_list = g_slist_remove(device->tech_list, tech);
1094         device->supported_techs &= ~(tech->tech_type);
1095         UAM_INFO("device->supported_techs: %8.8X", device->supported_techs);
1096         __free_dev_tech_info(tech);
1097
1098         if (UAM_TECH_TYPE_NONE == device->supported_techs) {
1099                 /* Remove device from global device list */
1100                 devices = g_slist_remove(devices, device);
1101
1102                 /* Remove device  from user's device list */
1103                 device->user->devices = g_slist_remove(device->user->devices, device);
1104
1105                 __free_user_device(device);
1106         }
1107
1108         /* Set/update registered device list to plugins */
1109         if (UAM_ERROR_NONE != _uam_pm_set_registered_devices(devices))
1110                 UAM_ERR("_uam_pm_set_registered_devices failed");
1111
1112         /* Set/update registered device list to cloud plugin */
1113         _uam_cloud_update_registered_devices();
1114
1115         FUNC_EXIT;
1116         return UAM_ERROR_NONE;
1117 }
1118
1119 int _uam_core_remove_device(const char *account,
1120         const uam_device_info_s *dev_info)
1121 {
1122         FUNC_ENTRY;
1123         int ret;
1124         GSList *l;
1125         uam_db_tech_info_t *tech;
1126         uam_db_device_info_t *device;
1127         uam_db_user_info_t *user;
1128
1129         retv_if(NULL == account, UAM_ERROR_INVALID_PARAMETER);
1130         retv_if(NULL == dev_info, UAM_ERROR_INVALID_PARAMETER);
1131
1132         /* Retrieve user from list */
1133         l = g_slist_find_custom(users, account, __compare_user_account);
1134         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
1135         user = l->data;
1136
1137         /* Retrieve device from list */
1138         l = g_slist_find_custom(devices, dev_info->device_id, __compare_device_id);
1139         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
1140         device = l->data;
1141         retv_if(user != device->user, UAM_ERROR_INVALID_PARAMETER);
1142         retv_if(!(device->supported_techs & dev_info->type), UAM_ERROR_INVALID_PARAMETER);
1143
1144         /* Retrieve tech info from list */
1145         l = g_slist_find_custom(device->tech_list,
1146                         &(dev_info->type), __compare_tech_type);
1147         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
1148         tech = l->data;
1149
1150         ret = __uam_remove_device(user->user_id, device, dev_info, tech);
1151
1152         FUNC_EXIT;
1153         return ret ;
1154 }
1155
1156 int _uam_core_remove_device_by_device_id(const char *device_id,
1157         int tech_type)
1158 {
1159         FUNC_ENTRY;
1160         int ret;
1161         GSList *l;
1162         uam_device_info_s dev_info;
1163         uam_db_tech_info_t *tech;
1164         uam_db_device_info_t *device;
1165
1166         retv_if(NULL == device_id, UAM_ERROR_INVALID_PARAMETER);
1167         retv_if(UAM_TECH_TYPE_NONE >= tech_type, UAM_ERROR_INVALID_PARAMETER);
1168         retv_if(UAM_TECH_TYPE_P2P < tech_type, UAM_ERROR_INVALID_PARAMETER);
1169
1170         /* Retrieve device from list */
1171         l = g_slist_find_custom(devices, device_id, __compare_device_id);
1172         retv_if(NULL == l, UAM_ERROR_NOT_REGISTERED);
1173         device = l->data;
1174         retv_if(!(device->supported_techs & tech_type), UAM_ERROR_NOT_REGISTERED);
1175
1176         /* Retrieve tech info from list */
1177         l = g_slist_find_custom(device->tech_list,
1178                         &tech_type, __compare_tech_type);
1179         retv_if(NULL == l, UAM_ERROR_INTERNAL);
1180         tech = l->data;
1181
1182         /* Get dev_info */
1183         ret = _uam_core_get_devcie_by_device_id(device_id, tech_type, &dev_info);
1184         retv_if(UAM_ERROR_NONE != ret, UAM_ERROR_NOT_REGISTERED);
1185
1186         ret = __uam_remove_device(device->user->user_id, device, &dev_info, tech);
1187
1188         FUNC_EXIT;
1189         return ret;
1190 }
1191
1192 int _uam_core_remove_device_by_mac(const char *mac)
1193 {
1194         FUNC_ENTRY;
1195         uam_db_tech_info_t *tech;
1196         uam_db_device_info_t *device;
1197         uam_device_info_s dev_info;
1198         int ret;
1199
1200         retv_if(NULL == mac, UAM_ERROR_INVALID_PARAMETER);
1201
1202         tech = __get_tech_info_by_mac(mac);
1203         retv_if(NULL == tech, UAM_ERROR_NOT_FOUND);
1204         device = tech->device;
1205
1206         ret = __copy_tech_info_to_device_info(tech, &dev_info);
1207         if (UAM_ERROR_NONE != ret) {
1208                 UAM_ERR("__copy_tech_info_to_device_info failed");
1209                 return ret;
1210         }
1211
1212         ret = __uam_remove_device(device->user->user_id, device, &dev_info, tech);
1213
1214         FUNC_EXIT;
1215         return ret;
1216 }
1217
1218 int _uam_core_update_device(const uam_device_info_s *a_device)
1219 {
1220         FUNC_ENTRY;
1221
1222         int ret = UAM_ERROR_NONE;
1223         GSList *l, *l1, *l2;
1224
1225         uam_device_info_s temp;
1226         uam_db_user_info_t *user = NULL;
1227         uam_db_device_info_t *device = NULL;
1228         uam_db_tech_info_t *tech = NULL;
1229
1230         /* Find all tech-devices in users' devices */
1231         for (l = users; NULL != l; l = g_slist_next(l)) {
1232                 user = l->data;
1233
1234                 l1 = g_slist_find_custom(user->devices,
1235                                 a_device->device_id, __compare_device_id);
1236                 if (NULL == l1) {
1237                         UAM_DBG("Valid user_id [%d] but Invalid device_id [%s]",
1238                                         user->user_id, a_device->device_id);
1239                         continue;
1240                 }
1241
1242                 device = l1->data;
1243                 if (!(device->supported_techs & a_device->type)) {
1244                         UAM_DBG("Valid device_id [%s] but Invalid tech type [%d]",
1245                                         device->device_id, a_device->type);
1246                         continue;
1247                 }
1248
1249                 /* Update discriminant for devices */
1250                 device->discriminant = a_device->discriminant;
1251                 device->os = a_device->operating_system;
1252
1253                 l2 = g_slist_find_custom(device->tech_list,
1254                                 &(a_device->type), __compare_tech_type);
1255                 if (NULL == l2) {
1256                         UAM_DBG("device->tech_list, tech type [%d] not found", a_device->type);
1257                         continue;
1258                 }
1259
1260                 tech = l2->data;
1261                 if (!tech) {
1262                         UAM_DBG("Device tech is NULL");
1263                         continue;
1264                 }
1265
1266                 /* Update discriminant for device-tech */
1267                 tech->discriminant = a_device->discriminant;
1268
1269                 /* Update device's updated information to database */
1270                 ret = __copy_tech_info_to_device_info(tech, &temp);
1271                 if (UAM_ERROR_NONE != ret) {
1272                         UAM_ERR("__copy_tech_info_to_device_info failed [%d]", ret);
1273                         return ret;
1274                 }
1275
1276                 ret = _uam_device_db_update_device(temp.device_id, temp.type,
1277                                 temp.mac, temp.ipv4_addr, temp.operating_system, temp.discriminant);
1278                 if (UAM_ERROR_NONE != ret) {
1279                         UAM_ERR("_uam_device_db_update_device failed [%d]", ret);
1280                         return ret;
1281                 }
1282         }
1283
1284         /* Set/update registered device list to plugins */
1285         ret = _uam_pm_set_registered_devices(devices);
1286         if (UAM_ERROR_NONE != ret) {
1287                 UAM_ERR("_uam_pm_set_registered_devices failed [%d]", ret);
1288                 return ret;
1289         }
1290
1291         /* Set/update registered device list to cloud plugin */
1292         _uam_cloud_update_registered_devices();
1293
1294         FUNC_EXIT;
1295         return ret;
1296 }
1297
1298 int _uam_core_get_default_user(uam_user_info_s *user_info)
1299 {
1300         FUNC_ENTRY;
1301         int ret;
1302         int user_id;
1303         GSList *l;
1304         uam_db_user_info_t *user;
1305
1306         retv_if(NULL == user_info, UAM_ERROR_INVALID_PARAMETER);
1307
1308         ret = _uam_core_add_user(&user_id, USER_ACCOUNT_DEFAULT, USER_NAME_DEFAULT);
1309         if ((UAM_ERROR_NONE != ret) && (UAM_ERROR_ALREADY_REGISTERED != ret)) {
1310                 UAM_ERR("_uam_core_add_user failed with %s", _uam_manager_error_to_str(ret));
1311                 return ret;
1312         }
1313
1314         l = g_slist_find_custom(users, USER_ACCOUNT_DEFAULT, __compare_user_account);
1315         retv_if(NULL == l, UAM_ERROR_INTERNAL);
1316         user = l->data;
1317
1318         memset(user_info, 0x00, sizeof(uam_user_info_s));
1319         g_strlcpy(user_info->account, user->account, UAM_USER_ACCOUNT_MAX_STRING_LEN);
1320         g_strlcpy(user_info->name, user->name, UAM_USER_NAME_MAX_STRING_LEN);
1321
1322         FUNC_EXIT;
1323         return UAM_ERROR_NONE;
1324 }
1325
1326 int _uam_core_get_users(int *count, uam_user_info_s **user_list)
1327 {
1328         FUNC_ENTRY;
1329         guint size;
1330         GSList *l;
1331
1332         size = g_slist_length(users);
1333         *user_list = g_new0(uam_user_info_s, size);
1334         *count = 0;
1335
1336         /* fetch users list from DB */
1337         for (l = users; l; l = g_slist_next(l)) {
1338                 uam_db_user_info_t *db_info = l->data;
1339
1340                 if (!db_info || !db_info->account)
1341                         continue;
1342
1343                 g_strlcpy((*user_list)[*count].account,
1344                                 db_info->account, UAM_USER_ACCOUNT_MAX_STRING_LEN);
1345                 if (db_info->name)
1346                         g_strlcpy((*user_list)[*count].name,
1347                                         db_info->name, UAM_USER_NAME_MAX_STRING_LEN);
1348
1349                 *count += 1;
1350         }
1351
1352         UAM_INFO("Count: %d", *count);
1353         FUNC_EXIT;
1354         return UAM_ERROR_NONE;
1355 }
1356
1357 int _uam_core_get_user_by_account(const char *account, uam_user_info_s *user)
1358 {
1359         FUNC_ENTRY;
1360         uam_db_user_info_t *db_info;
1361         GSList *l;
1362
1363         retv_if(NULL == account, UAM_ERROR_INVALID_PARAMETER);
1364
1365         l = g_slist_find_custom(users, account, __compare_user_account);
1366         retv_if(NULL == l, UAM_ERROR_NOT_FOUND);
1367         db_info = l->data;
1368
1369         g_strlcpy(user->account, db_info->account, UAM_USER_ACCOUNT_MAX_STRING_LEN);
1370         if (db_info->name)
1371                 g_strlcpy(user->name, db_info->name, UAM_USER_NAME_MAX_STRING_LEN);
1372
1373
1374         FUNC_EXIT;
1375         return UAM_ERROR_NONE;
1376 }
1377
1378 int _uam_core_get_devcie_by_device_id(
1379                 const char *device_id, int tech_type, uam_device_info_s *device)
1380 {
1381         FUNC_ENTRY;
1382         uam_db_device_info_t *db_info;
1383         GSList *l;
1384         GSList *l1;
1385
1386         retv_if(NULL == device_id, UAM_ERROR_INVALID_PARAMETER);
1387         retv_if(UAM_TECH_TYPE_NONE >= tech_type, UAM_ERROR_INVALID_PARAMETER);
1388         retv_if(UAM_TECH_TYPE_P2P < tech_type, UAM_ERROR_INVALID_PARAMETER);
1389
1390         l = g_slist_find_custom(devices, device_id, __compare_device_id);
1391         retv_if(NULL == l, UAM_ERROR_NOT_FOUND);
1392         db_info = l->data;
1393         retv_if(!(tech_type & db_info->supported_techs), UAM_ERROR_NOT_FOUND);
1394
1395         memset(device, 0x00, sizeof(uam_device_info_s));
1396
1397         for (l1 = db_info->tech_list; NULL != l1; l1 = g_slist_next(l1)) {
1398                 uam_db_tech_info_t *tech = l1->data;
1399                 GSList *l2;
1400
1401                 if (!tech || !tech->addresses || (tech->tech_type != tech_type))
1402                         continue;
1403
1404                 for (l2 = tech->addresses; NULL != l2; l2 = g_slist_next(l2)) {
1405                         uam_db_address_info_t *addr = l2->data;
1406
1407                         if (!addr)
1408                                 continue;
1409
1410                         __uam_core_copy_addr(device, addr);
1411                 }
1412
1413                 device->operating_system = db_info->os;
1414                 g_strlcpy(device->device_id, db_info->device_id,
1415                                 UAM_DEVICE_ID_MAX_STRING_LEN);
1416                 device->type = tech->tech_type;
1417                 device->discriminant = tech->discriminant;
1418         }
1419
1420         retv_if(UAM_TECH_TYPE_NONE == device->type, UAM_ERROR_NOT_FOUND);
1421
1422         FUNC_EXIT;
1423         return UAM_ERROR_NONE;
1424 }
1425
1426 int _uam_core_get_devcie_by_mac(const char *mac, uam_device_info_s *device)
1427 {
1428         FUNC_ENTRY;
1429         int ret;
1430         uam_db_tech_info_t *tech;
1431
1432         retv_if(NULL == mac, UAM_ERROR_INVALID_PARAMETER);
1433
1434         tech = __get_tech_info_by_mac(mac);
1435         retv_if(NULL == tech, UAM_ERROR_NOT_FOUND);
1436
1437         ret = __copy_tech_info_to_device_info(tech, device);
1438         if (UAM_ERROR_NONE != ret) {
1439                 UAM_ERR("__copy_tech_info_to_device_info failed");
1440                 return ret;
1441         }
1442
1443         FUNC_EXIT;
1444         return ret;
1445 }
1446
1447 int _uam_core_get_user_by_device_id(const char *device_id, uam_user_info_s *user)
1448 {
1449         FUNC_ENTRY;
1450         uam_db_device_info_t *dev;
1451         GSList *l;
1452
1453         retv_if(NULL == device_id, UAM_ERROR_INVALID_PARAMETER);
1454
1455         l = g_slist_find_custom(devices, device_id, __compare_device_id);
1456         retv_if(NULL == l, UAM_ERROR_NOT_FOUND);
1457         dev = l->data;
1458
1459         g_strlcpy(user->account, dev->user->account, UAM_USER_ACCOUNT_MAX_STRING_LEN);
1460         if (dev->user->name)
1461                 g_strlcpy(user->name, dev->user->name, UAM_USER_NAME_MAX_STRING_LEN);
1462
1463         FUNC_EXIT;
1464         return UAM_ERROR_NONE;
1465 }
1466
1467 int _uam_core_get_user_by_mac(const char *mac, uam_user_info_s *user)
1468 {
1469         FUNC_ENTRY;
1470         uam_db_tech_info_t *tech;
1471
1472         retv_if(NULL == mac, UAM_ERROR_INVALID_PARAMETER);
1473
1474         tech = __get_tech_info_by_mac(mac);
1475         retv_if(NULL == tech, UAM_ERROR_NOT_FOUND);
1476
1477         g_strlcpy(user->account, tech->device->user->account, UAM_USER_ACCOUNT_MAX_STRING_LEN);
1478         if (tech->device->user->name)
1479                 g_strlcpy(user->name, tech->device->user->name, UAM_USER_NAME_MAX_STRING_LEN);
1480
1481         FUNC_EXIT;
1482         return UAM_ERROR_NONE;
1483 }
1484
1485 int _uam_core_get_devices(int *count, uam_device_info_s **device_list)
1486 {
1487         FUNC_ENTRY;
1488         int ret = UAM_ERROR_NONE;
1489
1490         ret = __get_uam_db_dev_list_to_uam_dev_list(devices, device_list, count);
1491
1492         FUNC_EXIT;
1493         return ret;
1494 }
1495
1496 int _uam_core_get_user_devices(const char *account,
1497                 int *count, uam_device_info_s **device_list)
1498 {
1499         FUNC_ENTRY;
1500         uam_db_user_info_t *user;
1501         GSList *l;
1502         int ret = UAM_ERROR_NONE;
1503
1504         l = g_slist_find_custom(users, account, __compare_user_account);
1505         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
1506         user = l->data;
1507
1508         ret = __get_uam_db_dev_list_to_uam_dev_list(user->devices, device_list, count);
1509
1510         FUNC_EXIT;
1511         return ret;
1512 }
1513
1514 int _uam_core_get_available_sensors(unsigned int *sensor_bitmask)
1515 {
1516         FUNC_ENTRY;
1517
1518         *sensor_bitmask = _uam_pm_get_avaliable_sensors();
1519
1520         FUNC_EXIT;
1521         return UAM_ERROR_NONE;
1522 }
1523
1524 gboolean _uam_core_is_sensor_ready(unsigned int sensor)
1525 {
1526         FUNC_ENTRY;
1527         gboolean is_ready;
1528
1529         is_ready = _uam_pm_is_sensor_ready(sensor);
1530         UAM_DBG("%8.8X is %s", sensor, (is_ready ? "Ready" : "NOT Ready"));
1531
1532         FUNC_EXIT;
1533         return is_ready;
1534 }
1535
1536 static uam_svc_dev_info_t *_uam_core_find_svc_dev_info(const char *device_id,
1537         uam_tech_type_e tech_type, const char *svc_name)
1538 {
1539         FUNC_ENTRY;
1540         uam_svc_dev_info_t *svc_dev = NULL;
1541         GSList *l;
1542
1543         for (l = svc_devs; NULL != l; l = g_slist_next(l)) {
1544                 svc_dev = l->data;
1545
1546                 if (!svc_dev || !svc_dev->device_id || !svc_dev->service)
1547                         continue;
1548
1549                 if ((0 == g_strcmp0(svc_dev->device_id, device_id)) &&
1550                                 (0 == g_strcmp0(svc_dev->service, svc_name)) &&
1551                                 (svc_dev->tech_type == tech_type)) {
1552                         UAM_DBG("Service device found in list");
1553                         return svc_dev;
1554                 }
1555         }
1556
1557         FUNC_EXIT;
1558         return NULL;
1559 }
1560
1561 static int _uam_core_update_svc_dev_info(const char *device_id, uam_tech_type_e tech_type,
1562         const char *svc_name, gboolean discriminant, unsigned long long last_seen,
1563         uam_ble_payload_s *payload_info)
1564 {
1565         FUNC_ENTRY;
1566         uam_svc_dev_info_t *svc = NULL;
1567
1568         retv_if(NULL == device_id, UAM_ERROR_INVALID_PARAMETER);
1569         retv_if(UAM_TECH_TYPE_NONE >= tech_type, UAM_ERROR_INVALID_PARAMETER);
1570         retv_if(UAM_TECH_TYPE_MAX <= tech_type, UAM_ERROR_INVALID_PARAMETER);
1571         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
1572
1573         svc = _uam_core_find_svc_dev_info(device_id, tech_type, svc_name);
1574         if (!svc) {
1575                 svc = g_new0(uam_svc_dev_info_t, 1);
1576                 svc->device_id = g_strdup(device_id);
1577                 svc->tech_type = tech_type;
1578                 svc->service = g_strdup(svc_name);
1579                 svc->payload = g_new0(uam_db_payload_info_t, 1);
1580                 __uam_copy_uam_payload_info(svc->payload, payload_info);
1581                 svc_devs = g_slist_append(svc_devs, svc);
1582         }
1583
1584         if (discriminant >= 0)
1585                 svc->discriminant = discriminant;
1586         if (last_seen >= 0)
1587                 svc->last_seen = last_seen;
1588         if (payload_info)
1589                 __uam_copy_uam_payload_info(svc->payload, payload_info);
1590
1591         UAM_DBG("Service [%s] device [%s] tech_type [%d] discriminant [%d] " \
1592                 "last_seen [%llu] payload primary key [%d]",
1593                 svc->service, svc->device_id, svc->tech_type, svc->discriminant,
1594                 svc->last_seen, svc->payload->primary_key);
1595
1596         FUNC_EXIT;
1597         return UAM_ERROR_NONE;
1598 }
1599
1600 static int _uam_core_update_svc_dev_info_discriminant(const char *device_id,
1601         uam_tech_type_e tech_type, const char *svc_name, gboolean discriminant)
1602 {
1603         FUNC_ENTRY;
1604         uam_svc_dev_info_t *svc = NULL;
1605
1606         retv_if(NULL == device_id, UAM_ERROR_INVALID_PARAMETER);
1607         retv_if(UAM_TECH_TYPE_NONE >= tech_type, UAM_ERROR_INVALID_PARAMETER);
1608         retv_if(UAM_TECH_TYPE_MAX <= tech_type, UAM_ERROR_INVALID_PARAMETER);
1609         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
1610
1611         svc = _uam_core_find_svc_dev_info(device_id, tech_type, svc_name);
1612         if (!svc) {
1613                 svc = g_new0(uam_svc_dev_info_t, 1);
1614                 svc->device_id = g_strdup(device_id);
1615                 svc->tech_type = tech_type;
1616                 svc->service = g_strdup(svc_name);
1617                 svc_devs = g_slist_append(svc_devs, svc);
1618         }
1619
1620         svc->discriminant = discriminant;
1621
1622         UAM_DBG("Service [%s] device [%s] tech_type [%d] discriminant [%d]]",
1623                 svc->service, svc->device_id, svc->tech_type, svc->discriminant);
1624
1625         FUNC_EXIT;
1626         return UAM_ERROR_NONE;
1627 }
1628
1629 int _uam_core_service_add_user(const char *svc_name, const char *account)
1630 {
1631         FUNC_ENTRY;
1632         GSList *l;
1633         int ret = UAM_ERROR_NONE;
1634         uam_db_user_info_t *user;
1635         uam_db_service_info_t *service;
1636
1637         retv_if(NULL == account, UAM_ERROR_INVALID_PARAMETER);
1638         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
1639
1640         /* Retrieve user from list */
1641         l = g_slist_find_custom(users, account, __compare_user_account);
1642         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
1643         user = l->data;
1644
1645         /* Retrieve service from list */
1646         l = g_slist_find_custom(services, svc_name, __compare_svc_name);
1647         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
1648         service = l->data;
1649
1650         retv_if(UAM_ERROR_NONE != __uam_db_begin_transaction(), UAM_ERROR_DB_FAILED);
1651         for (l = user->devices; NULL != l; l = g_slist_next(l)) {
1652                 uam_db_device_info_t *device = l->data;
1653                 GSList *l1;
1654
1655                 if (!device)
1656                         continue;
1657
1658                 for (l1 = device->tech_list; NULL != l1; l1 = g_slist_next(l1)) {
1659                         uam_db_tech_info_t *tech = l1->data;
1660                         char *mac;
1661                         GSList *l2;
1662
1663                         if (!tech)
1664                                 continue;
1665
1666                         l2 = g_slist_find_custom(tech->svc_list, svc_name,
1667                                         __compare_svc_name);
1668                         if (NULL != l2)
1669                                 continue;
1670
1671                         __add_service_to_dev_tech_mapping(tech, service);
1672
1673                         mac = __get_mac_addr(tech);
1674                         /* Insert device service info to db */
1675                         ret = _uam_db_insert_device_service_info(device->device_id,
1676                                                 tech->tech_type, mac, service->name, service->cycle,
1677                                                 device->discriminant, 0);
1678                         if (UAM_ERROR_NONE != ret) {
1679                                 UAM_WARN("Device service addition to persistent DB failed");
1680                                 __uam_db_end_transaction(0);
1681                                 return ret;
1682                         }
1683                         ret = _uam_core_update_svc_dev_info(device->device_id, tech->tech_type,
1684                                                 service->name, device->discriminant, 0, NULL);
1685                         if (UAM_ERROR_NONE != ret) {
1686                                 UAM_WARN("Device service addition to service device mapping failed");
1687                                 __uam_db_end_transaction(0);
1688                                 return ret;
1689                         }
1690                 }
1691         }
1692
1693         __uam_db_end_transaction(1);
1694
1695         FUNC_EXIT;
1696         return ret;
1697 }
1698
1699 int _uam_core_service_remove_user(const char *svc_name, const char *account)
1700 {
1701         FUNC_ENTRY;
1702         GSList *l;
1703         uam_db_user_info_t *user;
1704         int ret;
1705
1706         retv_if(NULL == account, UAM_ERROR_INVALID_PARAMETER);
1707         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
1708
1709         /* Retrieve user from list */
1710         l = g_slist_find_custom(users, account, __compare_user_account);
1711         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
1712         user = l->data;
1713
1714         /* Retrieve service from list */
1715         l = g_slist_find_custom(services, svc_name, __compare_svc_name);
1716         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
1717
1718         retv_if(UAM_ERROR_NONE != __uam_db_begin_transaction(), UAM_ERROR_DB_FAILED);
1719         for (l = user->devices; NULL != l; l = g_slist_next(l)) {
1720                 uam_db_device_info_t *device = l->data;
1721                 GSList *l1;
1722
1723                 if (!device)
1724                         continue;
1725
1726                 for (l1 = device->tech_list; NULL != l1; l1 = g_slist_next(l1)) {
1727                         uam_db_tech_info_t *tech = l1->data;
1728                         char *mac;
1729                         GSList *l2;
1730
1731                         if (!tech)
1732                                 continue;
1733
1734                         l2 = g_slist_find_custom(tech->svc_list, svc_name,
1735                                         __compare_svc_name);
1736                         if (NULL == l2)
1737                                 continue;
1738
1739                         UAM_DBG("Service %s found, remove it from list", svc_name);
1740                         __remove_service_to_dev_tech_mapping(
1741                                         tech, (uam_db_service_info_t *)l2->data);
1742
1743                         mac = __get_mac_addr(tech);
1744                         /* Remove service-device from DB */
1745                         ret = _uam_db_delete_device_service_info(device->device_id,
1746                                         tech->tech_type, mac, svc_name);
1747                         if (UAM_ERROR_NONE != ret) {
1748                                 UAM_WARN("Device service removal from persistent DB failed");
1749                                 __uam_db_end_transaction(0);
1750                                 return ret;
1751                         }
1752                 }
1753         }
1754         __uam_db_end_transaction(1);
1755
1756         FUNC_EXIT;
1757         return UAM_ERROR_NONE;
1758 }
1759
1760 static uam_db_tech_info_t *__uam_core_get_dev_tech_info(const char *device_id, int tech_type)
1761 {
1762         FUNC_ENTRY;
1763         uam_db_device_info_t *device;
1764         GSList *l;
1765
1766         retv_if(NULL == device_id, NULL);
1767         retv_if(UAM_TECH_TYPE_NONE >= tech_type, NULL);
1768         retv_if(UAM_TECH_TYPE_MAX <= tech_type, NULL);
1769
1770         l = g_slist_find_custom(devices, device_id, __compare_device_id);
1771         if (NULL == l) {
1772                 UAM_DBG("DeviceId [%s] is not in the list", device_id);
1773                 return NULL;
1774         }
1775
1776         device = l->data;
1777         if (!device || !(device->supported_techs & tech_type)) {
1778                 UAM_DBG("Device type [0x%2.2X] for deviceId [%s] not found",
1779                                 tech_type, device_id);
1780                 return NULL;
1781         }
1782
1783         for (l = device->tech_list; NULL != l; l = g_slist_next(l)) {
1784                 uam_db_tech_info_t *tech = l->data;
1785
1786                 if (!tech)
1787                         continue;
1788
1789                 if (tech_type == tech->tech_type) {
1790                         UAM_DBG("DeviceId [%s], Device type [0x%2.2X] found",
1791                                         device_id, tech_type);
1792                         return tech;
1793                 }
1794         }
1795
1796         UAM_DBG("DeviceId [%s], Device type [0x%2.2X] not found", device_id, tech_type);
1797         FUNC_EXIT;
1798         return NULL;
1799 }
1800
1801 int _uam_core_service_add_device(const char *svc_name, const char *device_id,
1802         int tech_type)
1803 {
1804         FUNC_ENTRY;
1805         GSList *l;
1806         char *mac;
1807         int ret = UAM_ERROR_NONE;
1808         uam_db_tech_info_t *tech_info;
1809         uam_db_service_info_t *service;
1810
1811         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
1812         retv_if(NULL == device_id, UAM_ERROR_INVALID_PARAMETER);
1813         retv_if(UAM_TECH_TYPE_NONE >= tech_type, UAM_ERROR_INVALID_PARAMETER);
1814         retv_if(UAM_TECH_TYPE_MAX <= tech_type, UAM_ERROR_INVALID_PARAMETER);
1815
1816         tech_info = __uam_core_get_dev_tech_info(device_id, tech_type);
1817         retv_if(NULL == tech_info, UAM_ERROR_INVALID_PARAMETER);
1818
1819         l = g_slist_find_custom(tech_info->svc_list, svc_name, __compare_svc_name);
1820         retv_if(NULL != l, UAM_ERROR_ALREADY_REGISTERED);
1821
1822         /* Retrieve service from list */
1823         l = g_slist_find_custom(services, svc_name, __compare_svc_name);
1824         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
1825         service = l->data;
1826
1827         __add_service_to_dev_tech_mapping(tech_info, service);
1828
1829         mac = __get_mac_addr(tech_info);
1830         /* Insert device service info to db */
1831         ret = _uam_db_insert_device_service_info(device_id, tech_type, mac,
1832                                 service->name, service->cycle, tech_info->discriminant, 0);
1833         if (UAM_ERROR_NONE != ret) {
1834                 UAM_WARN("Device service addition to persistent DB failed");
1835                 return ret;
1836         }
1837         ret = _uam_core_update_svc_dev_info(device_id, tech_type, service->name,
1838                         tech_info->discriminant, 0, NULL);
1839         if (UAM_ERROR_NONE != ret) {
1840                 UAM_WARN("Device service addition to svc dev mapping failed");
1841                 return ret;
1842         }
1843
1844         FUNC_EXIT;
1845         return UAM_ERROR_NONE;
1846 }
1847
1848 int _uam_core_service_remove_device(const char *svc_name,
1849         const char *device_id, int tech_type)
1850 {
1851         FUNC_ENTRY;
1852         GSList *l;
1853         char *mac;
1854         uam_db_tech_info_t *tech_info;
1855         int ret = UAM_ERROR_NONE;
1856
1857         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
1858         retv_if(NULL == device_id, UAM_ERROR_INVALID_PARAMETER);
1859         retv_if(UAM_TECH_TYPE_NONE >= tech_type, UAM_ERROR_INVALID_PARAMETER);
1860         retv_if(UAM_TECH_TYPE_MAX <= tech_type, UAM_ERROR_INVALID_PARAMETER);
1861
1862         /* Retrieve service from list */
1863         l = g_slist_find_custom(services, svc_name, __compare_svc_name);
1864         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
1865
1866         tech_info = __uam_core_get_dev_tech_info(device_id, tech_type);
1867         retv_if(NULL == tech_info, UAM_ERROR_INVALID_PARAMETER);
1868
1869         l = g_slist_find_custom(tech_info->svc_list, svc_name, __compare_svc_name);
1870         retv_if(NULL == l, UAM_ERROR_NOT_REGISTERED);
1871
1872         __remove_service_to_dev_tech_mapping(tech_info, (uam_db_service_info_t *)l->data);
1873
1874         mac = __get_mac_addr(tech_info);
1875         /* Remove service-device from DB */
1876         ret = _uam_db_delete_device_service_info(
1877                         device_id, tech_type, mac, svc_name);
1878         if (UAM_ERROR_NONE != ret) {
1879                 UAM_ERR("Device service removal from persistent DB failed");
1880                 return ret;
1881         }
1882
1883         FUNC_EXIT;
1884         return UAM_ERROR_NONE;
1885 }
1886
1887 int _uam_core_service_set_device_discriminant(const char *svc_name,
1888                 const char *device_id, int tech_type, gboolean discriminant)
1889 {
1890         FUNC_ENTRY;
1891         GSList *l;
1892         int ret = UAM_ERROR_NONE;
1893         char *mac;
1894         uam_db_tech_info_t *tech_info;
1895         uam_db_service_info_t *service;
1896
1897         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
1898         retv_if(NULL == device_id, UAM_ERROR_INVALID_PARAMETER);
1899         retv_if(UAM_TECH_TYPE_NONE >= tech_type, UAM_ERROR_INVALID_PARAMETER);
1900         retv_if(UAM_TECH_TYPE_MAX <= tech_type, UAM_ERROR_INVALID_PARAMETER);
1901
1902         tech_info = __uam_core_get_dev_tech_info(device_id, tech_type);
1903         retv_if(NULL == tech_info, UAM_ERROR_INVALID_PARAMETER);
1904
1905         /* Retrieve service from list */
1906         l = g_slist_find_custom(services, svc_name, __compare_svc_name);
1907         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
1908         service = l->data;
1909
1910         mac = __get_mac_addr(tech_info);
1911         /* Insert device service info to db */
1912         ret = _uam_db_update_device_service_discriminant(device_id,
1913                                 tech_type, mac, service->name, discriminant);
1914         if (UAM_ERROR_NONE != ret) {
1915                 UAM_WARN("Device service discriminant update to persistent DB failed");
1916                 return ret;
1917         }
1918         ret = _uam_core_update_svc_dev_info_discriminant(device_id,
1919                                 tech_type, service->name, discriminant);
1920         if (UAM_ERROR_NONE != ret) {
1921                 UAM_WARN("Device service discriminant mapping update failed");
1922                 return ret;
1923         }
1924
1925         FUNC_EXIT;
1926         return UAM_ERROR_NONE;
1927 }
1928
1929 int _uam_core_service_get_device_discriminant(const char *svc_name,
1930                 const char *device_id, int tech_type, gboolean *discriminant)
1931 {
1932         FUNC_ENTRY;
1933         uam_svc_dev_info_t *svc_dev;
1934
1935         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
1936         retv_if(NULL == device_id, UAM_ERROR_INVALID_PARAMETER);
1937         retv_if(UAM_TECH_TYPE_NONE >= tech_type, UAM_ERROR_INVALID_PARAMETER);
1938         retv_if(UAM_TECH_TYPE_MAX <= tech_type, UAM_ERROR_INVALID_PARAMETER);
1939
1940         svc_dev = _uam_core_find_svc_dev_info(device_id, tech_type, svc_name);
1941         retv_if(NULL == svc_dev, UAM_ERROR_INVALID_PARAMETER);
1942         *discriminant = (gboolean)svc_dev->discriminant;
1943
1944         FUNC_EXIT;
1945         return UAM_ERROR_NONE;
1946 }
1947
1948 int _uam_core_service_get_device_last_seen(const char *svc_name,
1949                 const char *device_id, int tech_type, unsigned long long *last_seen)
1950 {
1951         FUNC_ENTRY;
1952         uam_svc_dev_info_t *svc_dev;
1953
1954         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
1955         retv_if(NULL == device_id, UAM_ERROR_INVALID_PARAMETER);
1956         retv_if(UAM_TECH_TYPE_NONE >= tech_type, UAM_ERROR_INVALID_PARAMETER);
1957         retv_if(UAM_TECH_TYPE_MAX <= tech_type, UAM_ERROR_INVALID_PARAMETER);
1958
1959         svc_dev = _uam_core_find_svc_dev_info(device_id, tech_type, svc_name);
1960         retv_if(NULL == svc_dev, UAM_ERROR_INVALID_PARAMETER);
1961         *last_seen = svc_dev->last_seen;
1962
1963         FUNC_EXIT;
1964         return UAM_ERROR_NONE;
1965 }
1966
1967 int _uam_core_set_service_detection_cycle(const char *svc_name, unsigned int new_cycle)
1968 {
1969         FUNC_ENTRY;
1970         GSList *l;
1971         uam_db_service_info_t *service;
1972         unsigned int elapsed_time;
1973
1974         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
1975         retv_if(UAM_DETECTION_CYCLE_MIN > new_cycle, UAM_ERROR_INVALID_PARAMETER);
1976         retv_if(0 != (new_cycle % UAM_DETECTION_CYCLE_MIN), UAM_ERROR_INVALID_PARAMETER);
1977
1978         l = g_slist_find_custom(services, svc_name, __compare_svc_name);
1979         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
1980         service = l->data;
1981
1982         elapsed_time = service->cycle - service->remaining_time;
1983         service->cycle = new_cycle;
1984         if (new_cycle < elapsed_time)
1985                 service->remaining_time = 0;
1986         else
1987                 service->remaining_time = new_cycle - elapsed_time;
1988
1989         /* Update service detection cycle in DB */
1990         if (UAM_ERROR_NONE != _uam_db_update_service_cycle(svc_name, new_cycle))
1991                 UAM_WARN("Service cycle updation to persistent DB failed");
1992
1993         FUNC_EXIT;
1994         return UAM_ERROR_NONE;
1995 }
1996
1997 int _uam_core_get_service_detection_cycle(const char *svc_name, unsigned int *cycle)
1998 {
1999         FUNC_ENTRY;
2000         GSList *l;
2001         uam_db_service_info_t *service;
2002
2003         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
2004         retv_if(NULL == cycle, UAM_ERROR_INVALID_PARAMETER);
2005
2006         l = g_slist_find_custom(services, svc_name, __compare_svc_name);
2007         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
2008         service = l->data;
2009         *cycle = service->cycle;
2010
2011         FUNC_EXIT;
2012         return UAM_ERROR_NONE;
2013 }
2014
2015 int _uam_core_set_detection_threshold(unsigned int sensor,
2016                 int presence_threshold, int absence_threshold)
2017 {
2018         FUNC_ENTRY;
2019         int ret;
2020
2021         ret = _uam_pm_set_detection_threshold(sensor,
2022                         presence_threshold, absence_threshold);
2023         if (UAM_ERROR_NONE != ret) {
2024                 UAM_ERR("_uam_pm_set_detection_threshold failed with %s",
2025                                 _uam_manager_error_to_str(ret));
2026                 return ret;
2027         }
2028
2029         FUNC_EXIT;
2030         return UAM_ERROR_NONE;
2031 }
2032
2033 static gboolean __start_detection(gpointer data)
2034 {
2035         FUNC_ENTRY;
2036         int ret;
2037         uam_db_service_info_t *service = NULL;
2038         unsigned int sensors;
2039         gboolean start_detection = FALSE;
2040         GSList *l;
2041         unsigned int presence_env_sensors;
2042         unsigned int absence_env_sensors;
2043
2044         presence_env_sensors = _uam_core_get_active_env_sensors(UAM_DETECT_PRESENCE);
2045         UAM_DBG("Presence Envionmental sensors: 0x%8.8X", presence_env_sensors);
2046
2047         absence_env_sensors = _uam_core_get_active_env_sensors(UAM_DETECT_ABSENCE);
2048         UAM_DBG("Absence Envionmental sensors: 0x%8.8X", absence_env_sensors);
2049
2050         if (0 != presence_env_sensors) {
2051                 /* Stop PRESENCE detection on active envionmental sensors*/
2052                 ret = _uam_pm_stop_detection(UAM_DETECT_PRESENCE, presence_env_sensors);
2053                 if (UAM_ERROR_NONE != ret)
2054                         UAM_ERR("Failed with error: %s (0x%4.4X)",
2055                                         _uam_manager_error_to_str(ret), ret);
2056         }
2057         if (0 != absence_env_sensors) {
2058                 /* Stop ABSENCE detection on envionmental sensors*/
2059                 ret = _uam_pm_stop_detection(UAM_DETECT_ABSENCE, absence_env_sensors);
2060                 if (UAM_ERROR_NONE != ret)
2061                         UAM_ERR("Failed with error: %s (0x%4.4X)",
2062                                         _uam_manager_error_to_str(ret), ret);
2063         }
2064
2065         for (l = services; NULL != l; l = g_slist_next(l)) {
2066                 service = l->data;
2067                 if (!service || !service->monitors)
2068                         continue;
2069
2070                 UAM_DBG("service: %p, monitors: %p", service, service->monitors);
2071                 UAM_DBG("service->remaining_time: %d", service->remaining_time);
2072                 service->remaining_time -= UAM_DETECTION_CYCLE_MIN;
2073                 if (0 >= service->remaining_time) {
2074                         start_detection = TRUE;
2075                         service->remaining_time = service->cycle;
2076                 }
2077         }
2078
2079         if (!start_detection)
2080                 goto done;
2081
2082         /* Get sensors on which PRESENCE detection to be started */
2083         sensors = _uam_core_get_active_sensors(UAM_DETECT_PRESENCE);
2084         UAM_DBG("PRESENCE sensors: 0x%8.8X", sensors);
2085
2086         /* Remove env sensors from active sensors */
2087         sensors &= ~presence_env_sensors;
2088         UAM_DBG("Presence Connectivity sensors: 0x%8.8X", sensors);
2089
2090         if (0 != sensors) {
2091                 /* Start PRESENCE detection */
2092                 ret = _uam_pm_start_detection(UAM_DETECT_PRESENCE, sensors);
2093                 if (UAM_ERROR_NONE != ret)
2094                         UAM_ERR("Failed with error: %s (0x%4.4X)",
2095                                         _uam_manager_error_to_str(ret), ret);
2096         }
2097
2098         /* Get sensors on which ABSENCE detection to be started */
2099         sensors = _uam_core_get_active_sensors(UAM_DETECT_ABSENCE);
2100         UAM_DBG("ABSENCE sensors: 0x%8.8X", sensors);
2101
2102         /* Remove env sensors from active sensors */
2103         sensors &= ~absence_env_sensors;
2104         UAM_DBG("ABSENCE Connectivity sensors: 0x%8.8X", sensors);
2105
2106         if (0 != sensors) {
2107                 /* Start ABSENCE detection */
2108                 ret = _uam_pm_start_detection(UAM_DETECT_ABSENCE, sensors);
2109                 if (UAM_ERROR_NONE != ret)
2110                         UAM_ERR("Failed with error: %s (0x%4.4X)",
2111                                         _uam_manager_error_to_str(ret), ret);
2112         }
2113
2114 done:
2115         if (0 != presence_env_sensors) {
2116                 /* Always Start PRESENCE detection on active envionmental sensors*/
2117                 ret = _uam_pm_start_detection(UAM_DETECT_PRESENCE, presence_env_sensors);
2118                 if (UAM_ERROR_NONE != ret)
2119                         UAM_ERR("Failed with error: %s (0x%4.4X)",
2120                                         _uam_manager_error_to_str(ret), ret);
2121         }
2122         if (0 != absence_env_sensors) {
2123                 /* Always Start ABSENCE detection on active envionmental sensors*/
2124                 ret = _uam_pm_start_detection(UAM_DETECT_ABSENCE, absence_env_sensors);
2125                 if (UAM_ERROR_NONE != ret)
2126                         UAM_ERR("Failed with error: %s (0x%4.4X)",
2127                                         _uam_manager_error_to_str(ret), ret);
2128         }
2129
2130         FUNC_EXIT;
2131         return TRUE;
2132 }
2133
2134 static int __uam_core_start_detection(int detection_type,
2135                 const char *svc_name, char *sender, unsigned int sensors)
2136 {
2137         FUNC_ENTRY;
2138         uam_monitor_info_t *monitor;
2139         uam_db_service_info_t *service;
2140         gboolean is_monitor_added = TRUE;
2141         GSList *l;
2142
2143         retv_if(NULL == sender, UAM_ERROR_INVALID_PARAMETER);
2144         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
2145
2146         l = g_slist_find_custom(services, svc_name, __compare_svc_name);
2147         if (!l) {
2148                 uam_db_service_info_t *default_svc = g_new0(uam_db_service_info_t, 1);
2149                 default_svc->name = g_strdup(UAM_SERVICE_DEFAULT);
2150                 default_svc->cycle = UAM_DETECTION_CYCLE_DEFAULT;
2151                 services = g_slist_append(services, default_svc);
2152                 l = services;
2153         }
2154
2155         retv_if(NULL == l, UAM_ERROR_NOT_FOUND);
2156         retv_if(NULL == l->data, UAM_ERROR_INTERNAL);
2157
2158         service = l->data;
2159         monitor = __uam_find_monitor(monitors, sender, svc_name, detection_type);
2160         if (!monitor) {
2161                 monitor = g_malloc0(sizeof(uam_monitor_info_t));
2162                 if (monitor) {
2163                         monitor->name = g_strdup(sender);
2164                         monitor->mode = detection_type;
2165                         monitor->service = service;
2166                         is_monitor_added = FALSE;
2167                 } else {
2168                         UAM_ERR("Memory allocation error");
2169                         return UAM_ERROR_OUT_OF_MEMORY;
2170                 }
2171         }
2172
2173         UAM_DBG("Name: %s, Service: %s, Mode: %d", monitor->name, svc_name, monitor->mode);
2174
2175         monitor->sensors |= sensors;
2176         if (!is_monitor_added) {
2177                 monitors = g_slist_append(monitors, monitor);
2178                 service->monitors = g_slist_append(service->monitors, monitor);
2179         }
2180
2181         /* Start detection */
2182         if (0 == detection_timer) {
2183                 __start_detection(NULL);
2184                 UAM_INFO("Monitor started detection, start timer");
2185                 detection_timer = g_timeout_add_seconds(
2186                                 UAM_DETECTION_CYCLE_MIN, __start_detection, NULL);
2187         }
2188
2189         FUNC_EXIT;
2190         return UAM_ERROR_NONE;
2191 }
2192
2193 static int __uam_core_stop_detection(int detection_type,
2194                 const char *svc_name, char *sender, unsigned int sensors)
2195 {
2196         FUNC_ENTRY;
2197         int ret = UAM_ERROR_NONE;
2198         unsigned int remaining_sensors;
2199         unsigned int active_sensors;
2200         uam_monitor_info_t *monitor;
2201         uam_db_service_info_t *service;
2202
2203         retv_if(NULL == sender, UAM_ERROR_INVALID_PARAMETER);
2204         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
2205
2206         monitor = __uam_find_monitor(monitors, sender, svc_name, detection_type);
2207         retv_if(NULL == monitor, UAM_ERROR_NOT_IN_OPERATION);
2208         service = monitor->service;
2209         retv_if(0 != g_strcmp0(service->name, svc_name), UAM_ERROR_NOT_IN_OPERATION);
2210
2211         /* Find sensors which are already monitoring */
2212         active_sensors = _uam_core_get_active_sensors(detection_type);
2213         UAM_DBG("sensors: 0x%8.8X, Active sensors: 0x%8.8X",
2214                         sensors, active_sensors);
2215
2216         /* Update monitor info for application */
2217         monitor->sensors &= ~sensors;
2218         if (0 == monitor->sensors) {
2219                 /*
2220                  * App requested to stop monitoring for all of its active sensors,
2221                  * remove its monitor info from list.
2222                  */
2223                 monitors = g_slist_remove(monitors, monitor);
2224                 if ((NULL == monitors) && (0 != detection_timer)) {
2225                         UAM_INFO("All monitors stopped detection, stop timer");
2226                         g_source_remove(detection_timer);
2227                         detection_timer = 0;
2228                 }
2229
2230                 service->monitors = g_slist_remove(service->monitors, monitor);
2231                 if (NULL == service->monitors)
2232                         service->remaining_time = 0;
2233
2234                 g_free(monitor->name);
2235                 g_free(monitor);
2236         }
2237
2238         /* Find sensors which are already monitoring */
2239         remaining_sensors = _uam_core_get_active_sensors(detection_type);
2240         UAM_DBG("Remaining sensors: 0x%8.8X", remaining_sensors);
2241
2242         if (active_sensors == remaining_sensors) {
2243                 UAM_INFO("NO need to stop monitoring");
2244                 return UAM_ERROR_NONE;
2245         }
2246
2247         /* Stop monitoring only for sensors which aren't required anymore */
2248         sensors = (active_sensors & ~remaining_sensors);
2249         ret = _uam_pm_stop_detection(detection_type, sensors);
2250         if (UAM_ERROR_NONE != ret)
2251                 UAM_ERR("Failed with error: %s (0x%4.4X)",
2252                                 _uam_manager_error_to_str(ret), ret);
2253
2254         FUNC_EXIT;
2255         return ret;
2256 }
2257
2258 int _uam_core_start_presence_detection(const char *svc_name, char *sender, unsigned int sensors)
2259 {
2260         FUNC_ENTRY;
2261         int ret;
2262
2263         ret = __uam_core_start_detection(UAM_DETECT_PRESENCE, svc_name, sender, sensors);
2264
2265         FUNC_EXIT;
2266         return ret;
2267 }
2268
2269 int _uam_core_stop_presence_detection(const char *svc_name, char *sender, unsigned int sensors)
2270 {
2271         FUNC_ENTRY;
2272         int ret;
2273
2274         ret = __uam_core_stop_detection(UAM_DETECT_PRESENCE, svc_name, sender, sensors);
2275
2276         FUNC_EXIT;
2277         return ret;
2278 }
2279
2280 int _uam_core_start_absence_detection(const char *svc_name, char *sender, unsigned int sensors)
2281 {
2282         FUNC_ENTRY;
2283         int ret;
2284
2285         ret = __uam_core_start_detection(UAM_DETECT_ABSENCE, svc_name, sender, sensors);
2286
2287         FUNC_EXIT;
2288         return ret;
2289 }
2290
2291 int _uam_core_stop_absence_detection(const char *svc_name, char *sender, unsigned int sensors)
2292 {
2293         FUNC_ENTRY;
2294         int ret;
2295
2296         ret = __uam_core_stop_detection(UAM_DETECT_ABSENCE, svc_name, sender, sensors);
2297
2298         FUNC_EXIT;
2299         return ret;
2300 }
2301
2302 int _uam_core_set_low_power_mode(unsigned int bitmask, gboolean mode)
2303 {
2304         FUNC_ENTRY;
2305         int ret;
2306
2307         UAM_INFO("bitmask [%x] mode [%d]", bitmask, mode);
2308         ret = _uam_pm_set_low_power_mode(bitmask, mode);
2309         if (UAM_ERROR_NONE != ret) {
2310                 UAM_ERR("_uam_pm_set_low_power_mode failed with [%x] %s",
2311                                 bitmask, _uam_manager_error_to_str(ret));
2312                 return ret;
2313         }
2314
2315         FUNC_EXIT;
2316         return UAM_ERROR_NONE;
2317 }
2318
2319 int _uam_core_get_detection_window(unsigned int *window)
2320 {
2321         FUNC_ENTRY;
2322
2323         retv_if(NULL == window, UAM_ERROR_INVALID_PARAMETER);
2324
2325         *window = detection_window;
2326
2327         FUNC_EXIT;
2328         return UAM_ERROR_NONE;
2329 }
2330
2331 int _uam_core_set_detection_window(unsigned int window)
2332 {
2333         FUNC_ENTRY;
2334
2335         retv_if(0 >= window, UAM_ERROR_INVALID_PARAMETER);
2336         retv_if(UAM_DETECTION_WINDOW_MAX < window, UAM_ERROR_INVALID_PARAMETER);
2337         retv_if(0 != (window % UAM_DETECTION_WINDOW_STEP), UAM_ERROR_INVALID_PARAMETER);
2338
2339         if (UAM_ERROR_NONE != _uam_pm_set_detection_window(window)) {
2340                 UAM_ERR("_uam_pm_set_detection_window(%d) failed", window);
2341                 return UAM_ERROR_INTERNAL;
2342         }
2343
2344         detection_window = window;
2345
2346         FUNC_EXIT;
2347         return UAM_ERROR_NONE;
2348 }
2349
2350 int _uam_core_init(void)
2351 {
2352         FUNC_ENTRY;
2353         GSList *db_users;
2354         GSList *db_devices;
2355         GSList *db_svc_list;
2356         GSList *db_adv_list;
2357         GSList *db_svc_dev_list;
2358         GSList *db_payload_list;
2359         GSList *l;
2360
2361         /* Init database */
2362         _uam_db_initialize();
2363
2364         /* Reset detecton window to default */
2365         detection_window = UAM_DETECTION_WINDOW_DEFAULT;
2366         if (UAM_ERROR_NONE != _uam_pm_set_detection_window(detection_window))
2367                 UAM_ERR("_uam_pm_set_detection_window(%d) failed", detection_window);
2368
2369         /* Fetch user list */
2370         db_users = _uam_db_get_all_users();
2371         if (!db_users) {
2372                 UAM_INFO_C("No users in database");
2373         }
2374         else {
2375                 for (l = db_users; NULL != l; l = g_slist_next(l)) {
2376                         db_user_info_t *info = l->data;
2377                         uam_db_user_info_t *user;
2378
2379                         if (!info)
2380                                 continue;
2381
2382                         user = g_new0(uam_db_user_info_t, 1);
2383                         user->user_id = info->user_id;
2384                         user->name = g_strdup(info->name);
2385                         user->account = g_strdup(info->account);
2386                         user->devices = NULL;
2387
2388                         users = g_slist_prepend(users, user);
2389                 }
2390         }
2391
2392         /* Fetch service list */
2393         db_svc_list = _uam_service_db_get_all_services();
2394         if (!db_svc_list) {
2395                 UAM_INFO_C("No services in database");
2396         }
2397         else {
2398                 for (l = db_svc_list; NULL != l; l = g_slist_next(l)) {
2399                         db_service_info_t *db_svc = l->data;
2400                         uam_db_service_info_t *service;
2401                         GSList *l1;
2402
2403                         if (!db_svc)
2404                                 continue;
2405
2406                         l1 = g_slist_find_custom(services,
2407                                         db_svc->service_name, __compare_svc_name);
2408                         if (!l1) {
2409                                 service = g_new0(uam_db_service_info_t, 1);
2410                                 service->name = g_strdup(db_svc->service_name);
2411                                 service->cycle = db_svc->cycle;
2412                                 service->presence_threshold = db_svc->presence_threshold;
2413                                 service->absence_threshold = db_svc->absence_threshold;
2414                                 services = g_slist_append(services, service);
2415                         }
2416                 }
2417         }
2418
2419         /* Fetch payload list */
2420         db_payload_list = _uam_db_get_all_payloads();
2421         if (!db_payload_list) {
2422                 UAM_INFO_C("No device payload in database");
2423         } else {
2424                 for (l = db_payload_list; NULL != l; l = g_slist_next(l)) {
2425                         db_payload_info_t *db_payload = l->data;
2426                         uam_db_payload_info_t *payload = g_new0(uam_db_payload_info_t, 1);
2427                         GSList *l1 = NULL;
2428
2429                         if (!db_payload)
2430                                 continue;
2431
2432                         l1 = g_slist_find_custom(payloads, db_payload, __compare_db_payload);
2433                         if (!l1) {
2434                                 payload = g_new0(uam_db_payload_info_t, 1);
2435                                 __uam_copy_uam_payload_info(payload, &(db_payload->payload_info));
2436                                 payload->device_id = g_strdup(db_payload->device_id);
2437                                 payload->tech_type = db_payload->type;
2438                                 payloads = g_slist_append(payloads, payload);
2439                         }
2440                 }
2441         }
2442
2443         /* Fetch svc dev list */
2444         db_svc_dev_list = _uam_db_get_service_devices_info();
2445         if (!db_svc_dev_list) {
2446                 UAM_INFO_C("No service devices in database");
2447         } else {
2448                 for (l = db_svc_dev_list; NULL != l; l = g_slist_next(l)) {
2449                         db_svc_dev_info_t *db_svc = l->data;
2450
2451                         _uam_core_update_svc_dev_info(db_svc->device_id, db_svc->type,
2452                                         db_svc->svc, db_svc->discriminant, db_svc->last_seen,
2453                                         &(db_svc->payload_info));
2454                 }
2455         }
2456
2457         /* Fetch device list */
2458         db_devices = _uam_device_db_get_all_devices();
2459         if (!db_devices) {
2460                 UAM_INFO_C("No Devices registered in database");
2461         }
2462         else {
2463                 for (l = db_devices; NULL != l; l = g_slist_next(l)) {
2464                         db_device_info_t *db_info = l->data;
2465                         uam_db_user_info_t *user;
2466                         GSList *svc_list = NULL;
2467                         GSList *svc_dev_list = NULL;
2468                         GSList *l1;
2469
2470                         if (!db_info)
2471                                 continue;
2472
2473                         l1 = g_slist_find_custom(users,
2474                                 &(db_info->user_id), __compare_user_id);
2475                         if (!l1) {
2476                                 UAM_ERR("Invalid user Id: %d", db_info->user_id);
2477                                 continue;
2478                         }
2479                         user = l1->data;
2480
2481                         /* Fetch device services from DB */
2482                         l1 = _uam_db_get_device_services(
2483                                 db_info->dev_info.device_id,
2484                                 db_info->dev_info.type,
2485                                 db_info->dev_info.mac);
2486
2487                         svc_list = __convert_db_svc_list_to_uam_svc_list(l1);
2488
2489                         svc_dev_list = _uam_core_find_svc_dev_list(&(db_info->dev_info));
2490                         __uam_core_add_dev_to_list(user, &(db_info->dev_info),
2491                                 db_info->presence_state, db_info->last_seen,
2492                                 svc_list, svc_dev_list);
2493                 }
2494         }
2495
2496         /* Fetch iBeacon adv list */
2497         db_adv_list = _uam_db_get_all_advs();
2498         if (!db_adv_list) {
2499                 UAM_INFO_C("No iBeacon adv in database");
2500         } else {
2501                 for (l = db_adv_list; NULL != l; l = g_slist_next(l)) {
2502                         db_adv_info_t *db_adv = l->data;
2503                         _uam_pm_add_ibeacon_adv(db_adv->adv_len, db_adv->iadv);
2504                 }
2505         }
2506
2507         g_slist_free_full(db_devices, g_free);
2508         g_slist_free_full(db_users, g_free);
2509         g_slist_free_full(db_svc_list, g_free);
2510         g_slist_free_full(db_adv_list, g_free);
2511         g_slist_free_full(db_svc_dev_list, g_free);
2512         g_slist_free_full(db_payload_list, g_free);
2513
2514         if (devices) {
2515                 /* Set/update registered device list to plugins */
2516                 if (UAM_ERROR_NONE != _uam_pm_set_registered_devices(devices))
2517                         UAM_ERR("_uam_pm_set_registered_devices failed");
2518
2519                 /* Set/update registered device list to cloud plugin */
2520                 _uam_cloud_update_registered_devices();
2521         }
2522
2523         FUNC_EXIT;
2524         return UAM_ERROR_NONE;
2525 }
2526
2527 void _uam_core_deinit(void)
2528 {
2529         FUNC_ENTRY;
2530         GSList *l;
2531
2532         /* de-init database */
2533         _uam_db_deinitialize();
2534
2535         /* Reset detecton window to default */
2536         detection_window = UAM_DETECTION_WINDOW_DEFAULT;
2537
2538         /* Release allocated memory for devices */
2539         g_slist_free_full(devices, __free_user_device);
2540         devices = NULL;
2541
2542         /* Release allocated memory for users */
2543         for (l = users; NULL != l; l = g_slist_next(l)) {
2544                 uam_db_user_info_t *user = l->data;
2545
2546                 if (!user)
2547                         continue;
2548
2549                 g_free(user->name);
2550                 g_free(user->account);
2551                 g_free(user);
2552         }
2553
2554         g_slist_free(users);
2555         users = NULL;
2556
2557         /* Release allocated memory for services */
2558         for (l = services; NULL != l; l = g_slist_next(l)) {
2559                 uam_db_service_info_t *service = l->data;
2560
2561                 if (!service)
2562                         continue;
2563
2564                 g_free(service->name);
2565                 g_free(service);
2566         }
2567         g_slist_free(services);
2568         services = NULL;
2569
2570         /* Release allocated memory for service devices */
2571         for (l = svc_devs; NULL != l; l = g_slist_next(l)) {
2572                 uam_svc_dev_info_t *svc_dev = l->data;
2573
2574                 if (!svc_dev)
2575                         continue;
2576
2577                 g_free(svc_dev->device_id);
2578                 g_free(svc_dev->service);
2579                 g_free(svc_dev->payload);
2580                 g_free(svc_dev);
2581         }
2582         g_slist_free(svc_devs);
2583         svc_devs = NULL;
2584
2585         /* Release allocated memory for payloads */
2586         for (l = payloads; NULL != l; l = g_slist_next(l)) {
2587                 uam_db_payload_info_t *payload = l->data;
2588
2589                 if (!payload)
2590                         continue;
2591                 g_free(payload->device_uid);
2592                 g_free(payload->bt_mac);
2593                 g_free(payload);
2594         }
2595         g_slist_free(payloads);
2596         payloads = NULL;
2597
2598         FUNC_EXIT;
2599 }
2600
2601 void _uam_core_handle_sensor_ready(unsigned int sensor, gboolean is_ready)
2602 {
2603         FUNC_ENTRY;
2604
2605         /* Send sensor state changed event over dbus */
2606         if (is_ready)
2607                 _uam_manager_send_event(NULL, UAM_EVENT_SENSOR_STATE_READY,
2608                                 g_variant_new("(iu)", UAM_ERROR_NONE, sensor));
2609         else
2610                 _uam_manager_send_event(NULL, UAM_EVENT_SENSOR_STATE_NOT_READY,
2611                                 g_variant_new("(iu)", UAM_ERROR_NONE, sensor));
2612
2613         FUNC_EXIT;
2614 }
2615
2616 int _uam_core_handle_device_added(int status,
2617                 int user_id, const uam_device_info_s *dev_info)
2618 {
2619         FUNC_ENTRY;
2620
2621         GSList *l;
2622         int ret = UAM_ERROR_NONE;
2623         GSList *svc_list = NULL;
2624         GSList *svc_dev_list = NULL;
2625         uam_db_user_info_t *user = NULL;
2626         uam_svc_dev_info_t *svc_dev = NULL;
2627
2628         UAM_INFO("[%d]", user_id);
2629
2630         /* Send reply over dbus for add device API */
2631         l = _uam_manager_get_request_list();
2632         for (; NULL != l; l = g_slist_next(l)) {
2633                 uam_request_context_t *info = l->data;
2634                 uam_device_info_s *dev;
2635                 GArray *out_param;
2636
2637                 if (!info || (UAM_REQUEST_ADD_DEVICE != info->function))
2638                         continue;
2639
2640                 dev = info->data;
2641                 if (!dev) {
2642                         UAM_WARN("info->data is NULL");
2643                         continue;
2644                 }
2645
2646                 if (dev->type != dev_info->type ||
2647                                 strcasecmp(dev->device_id, dev_info->device_id)) {
2648                         UAM_WARN("[%d != %d] || [%s != %s]", dev->type, dev_info->type,
2649                                         dev->device_id, dev_info->device_id);
2650                         continue;
2651                 }
2652
2653                 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
2654                 g_array_append_vals(out_param, dev_info, sizeof(uam_device_info_s));
2655                 _uam_manager_method_return(info->context, out_param, status);
2656
2657                 _uam_remove_timer(info->tid);
2658
2659                 _uam_manager_remove_req_ctxt_from_list(info);
2660
2661                 break;
2662         }
2663
2664         if (UAM_ERROR_NONE != status) {
2665                 __send_device_event(status, UAM_EVENT_DEVICE_ADDED, dev_info);
2666                 return status;
2667         }
2668
2669         if (0 > user_id) {
2670                 int id = 0;
2671                 l = g_slist_find_custom(users,
2672                                 USER_ACCOUNT_DEFAULT, __compare_user_account);
2673                 if (NULL == l) {
2674                         ret = _uam_core_add_user(&id, USER_ACCOUNT_DEFAULT, USER_NAME_DEFAULT);
2675                         if (UAM_ERROR_NONE != ret) {
2676                                 UAM_ERR("_uam_core_add_user failed with %s",
2677                                                 _uam_manager_error_to_str(ret));
2678                                 __send_device_event(ret, UAM_EVENT_DEVICE_ADDED, dev_info);
2679                                 return ret;
2680                         }
2681                 }
2682                 user_id = id;
2683         }
2684         l = g_slist_find_custom(users, &user_id, __compare_user_id);
2685         if (NULL == l) {
2686                 UAM_ERR("Invalid user Id: %d", user_id);
2687                 ret = UAM_ERROR_NOT_FOUND;
2688                 __send_device_event(ret, UAM_EVENT_DEVICE_ADDED, dev_info);
2689                 return ret;
2690         }
2691         user = l->data;
2692
2693         /* Get default service and add it to device's service list by default */
2694         l = g_slist_find_custom(services, UAM_SERVICE_DEFAULT, __compare_svc_name);
2695         if (!l) {
2696                 uam_db_service_info_t *service = g_new0(uam_db_service_info_t, 1);
2697                 service->name = g_strdup(UAM_SERVICE_DEFAULT);
2698                 service->cycle = UAM_DETECTION_CYCLE_DEFAULT;
2699                 services = g_slist_append(services, service);
2700                 svc_list = g_slist_append(svc_list, service);
2701         } else {
2702                 uam_db_service_info_t *service = l->data;
2703                 svc_list = g_slist_append(svc_list, service);
2704         }
2705
2706         /** updates for svc dev*/
2707         ret = _uam_core_update_svc_dev_info(dev_info->device_id, dev_info->type,
2708                                 UAM_SERVICE_DEFAULT, dev_info->discriminant, 0, NULL);
2709         if (UAM_ERROR_NONE != ret) {
2710                 UAM_WARN("Device service mappiing update failed");
2711                 __send_device_event(ret, UAM_EVENT_DEVICE_ADDED, dev_info);
2712                 return ret;
2713         }
2714
2715         svc_dev = _uam_core_find_svc_dev_info(dev_info->device_id,
2716                         dev_info->type, UAM_SERVICE_DEFAULT);
2717         svc_dev_list = g_slist_append(svc_dev_list, svc_dev);
2718         __uam_core_add_dev_to_list(user, dev_info, UAM_PRESENCE_STATE_PRESENT,
2719                         dev_info->last_seen, svc_list, svc_dev_list);
2720
2721         /** Start database transaction */
2722         retv_if(UAM_ERROR_NONE != __uam_db_begin_transaction(), UAM_ERROR_DB_FAILED);
2723
2724         /* Add device to database */
2725         ret = _uam_device_db_insert_device_info(user->user_id, dev_info,
2726                         UAM_PRESENCE_STATE_PRESENT, dev_info->last_seen);
2727         if (UAM_ERROR_NONE != ret) {
2728                 UAM_WARN("Device addition to persistent DB failed");
2729                 __uam_db_end_transaction(0);
2730                 return ret;
2731         }
2732
2733         /* Insert device service info to db */
2734         ret =  _uam_db_insert_device_service_info(
2735                                 dev_info->device_id, dev_info->type, dev_info->mac,
2736                                 UAM_SERVICE_DEFAULT, UAM_DETECTION_CYCLE_DEFAULT,
2737                                 dev_info->discriminant, 0);
2738         if (UAM_ERROR_NONE != ret) {
2739                 UAM_WARN("Device service addition to persistent DB failed");
2740                 __send_device_event(ret, UAM_EVENT_DEVICE_ADDED, dev_info);
2741                 __uam_db_end_transaction(0);
2742                 return ret;
2743         }
2744         __uam_db_end_transaction(1);
2745         /** End database transaction */
2746
2747         /* Send device added event to application */
2748         __send_device_event(ret, UAM_EVENT_DEVICE_ADDED, dev_info);
2749
2750         /* Set/update registered device list to plugins */
2751         ret = _uam_pm_set_registered_devices(devices);
2752         if (UAM_ERROR_NONE != ret) {
2753                 UAM_ERR("_uam_pm_set_registered_devices failed");
2754                 return ret;
2755         }
2756
2757         _uam_cloud_send_device_added(status, (user ? user->account : NULL), dev_info);
2758
2759         /* Set/update registered device list to cloud plugin */
2760         if (UAM_ERROR_NONE == status)
2761                 _uam_cloud_update_registered_devices();
2762
2763         FUNC_EXIT;
2764         return ret;
2765 }
2766
2767 void __send_sensor_presence_event(uam_sensor_info_s *sensor_info, unsigned int sensor)
2768 {
2769         FUNC_ENTRY;
2770         GSList *l;
2771         unsigned long long timestamp;
2772
2773         UAM_INFO("sensor 0x[%8.8X]", sensor);
2774
2775         if (NULL == sensor_info) {
2776                 _uam_manager_send_event(NULL, UAM_EVENT_PRESENCE_DETECTED,
2777                         g_variant_new("(utiidddd)", sensor, 0, 0, 0, 0, 0, 0, 0));
2778                 UAM_DBG("Sent UAM_EVENT_PRESENCE_DETECTED for 0x%8.8X", sensor);
2779                 FUNC_EXIT;
2780                 return;
2781         }
2782
2783         timestamp = _uam_get_timestamp();
2784
2785         if (UAM_SENSOR_BITMASK_LIGHT != sensor) {
2786                 _uam_manager_send_event(NULL, UAM_EVENT_PRESENCE_DETECTED,
2787                         g_variant_new("(utiidddd)", sensor, timestamp,
2788                         sensor_info->accuracy, sensor_info->count, sensor_info->values[0],
2789                         sensor_info->values[1], sensor_info->values[2], sensor_info->values[3]));
2790                 UAM_DBG("Sent UAM_EVENT_PRESENCE_DETECTED for 0x%8.8X", sensor);
2791                 FUNC_EXIT;
2792                 return;
2793         }
2794
2795         // service specific light detection threshold
2796         for (l = services; NULL != l; l = g_slist_next(l)) {
2797                 uam_db_service_info_t *svc = l->data;
2798                 GSList *l1;
2799
2800                 if (!svc || !svc->monitors)
2801                         continue;
2802
2803                 UAM_INFO("service [%s] sensor value [%f] threshold [%u]",
2804                                 svc->name, sensor_info->values[0], svc->presence_threshold);
2805
2806                 if (sensor_info->values[0] < svc->presence_threshold)
2807                         continue;
2808
2809                 for (l1 = svc->monitors; NULL != l1; l1 = g_slist_next(l1)) {
2810                         uam_monitor_info_t *mon = l1->data;
2811
2812                         if (!mon)
2813                                 continue;
2814
2815                         UAM_INFO("monitor [%s] sensors 0x[%8.8X]",
2816                                         mon->name, mon->sensors);
2817
2818                         if (!(mon->sensors & sensor))
2819                                 continue;
2820
2821                         if (UAM_DETECT_PRESENCE != mon->mode)
2822                                 continue;
2823
2824                         _uam_manager_send_event(mon->name, UAM_EVENT_PRESENCE_DETECTED,
2825                                 g_variant_new("(utiidddd)", sensor, timestamp,
2826                                 sensor_info->accuracy, sensor_info->count, sensor_info->values[0],
2827                                 sensor_info->values[1], sensor_info->values[2], sensor_info->values[3]));
2828                         UAM_DBG("Sent UAM_EVENT_PRESENCE_DETECTED to %s for 0x%8.8X",
2829                                         mon->name, sensor);
2830                 }
2831         }
2832
2833         FUNC_EXIT;
2834 }
2835
2836 static void __send_sensor_absence_event(uam_sensor_info_s *sensor_info,
2837         unsigned int sensor)
2838 {
2839         FUNC_ENTRY;
2840         GSList *l;
2841
2842         UAM_INFO("sensor 0x[%8.8X]", sensor);
2843
2844         if (NULL == sensor_info) {
2845                 _uam_manager_send_event(NULL, UAM_EVENT_ABSENCE_DETECTED,
2846                         g_variant_new("(utiidddd)", sensor, 0, 0, 0, 0, 0, 0, 0));
2847                 UAM_DBG("Sent UAM_EVENT_ABSENCE_DETECTED for 0x%8.8X", sensor);
2848                 FUNC_EXIT;
2849                 return;
2850         }
2851
2852         if (UAM_SENSOR_BITMASK_LIGHT != sensor) {
2853                 _uam_manager_send_event(NULL, UAM_EVENT_ABSENCE_DETECTED,
2854                         g_variant_new("(utiidddd)", sensor, sensor_info->timestamp,
2855                         sensor_info->accuracy, sensor_info->count, sensor_info->values[0],
2856                         sensor_info->values[1], sensor_info->values[2], sensor_info->values[3]));
2857                 UAM_DBG("Sent UAM_EVENT_ABSENCE_DETECTED for 0x%8.8X", sensor);
2858                 FUNC_EXIT;
2859                 return;
2860         }
2861
2862         // service specific light detection threshold
2863         for (l = services; NULL != l; l = g_slist_next(l)) {
2864                 uam_db_service_info_t *svc = l->data;
2865                 GSList *l1;
2866
2867                 if (!svc || !svc->monitors)
2868                         continue;
2869
2870                 UAM_INFO("service [%s] sensor value [%f] threshold [%u]",
2871                                 svc->name, sensor_info->values[0], svc->absence_threshold);
2872
2873                 if (sensor_info->values[0] > svc->absence_threshold)
2874                         continue;
2875
2876                 for (l1 = svc->monitors; NULL != l1; l1 = g_slist_next(l1)) {
2877                         uam_monitor_info_t *mon = l1->data;
2878
2879                         if (!mon)
2880                                 continue;
2881
2882                         if (!(mon->sensors & sensor))
2883                                 continue;
2884
2885                         if (UAM_DETECT_PRESENCE != mon->mode)
2886                                 continue;
2887
2888                         _uam_manager_send_event(mon->name, UAM_EVENT_ABSENCE_DETECTED,
2889                                 g_variant_new("(utiidddd)", sensor, sensor_info->timestamp,
2890                                 sensor_info->accuracy, sensor_info->count, sensor_info->values[0],
2891                                 sensor_info->values[1], sensor_info->values[2], sensor_info->values[3]));
2892                         UAM_DBG("Sent UAM_EVENT_ABSENCE_DETECTED for 0x%8.8X", sensor);
2893                 }
2894         }
2895
2896         FUNC_EXIT;
2897 }
2898
2899 void __send_user_presence_event(uam_db_tech_info_t *tech, unsigned int sensor,
2900                 uam_device_info_s *dev_info)
2901 {
2902         FUNC_ENTRY;
2903
2904         GSList *l;
2905         uam_db_user_info_t *user;
2906         uam_svc_dev_info_t *svc_dev = NULL;
2907         gboolean live_monitoring = FALSE;
2908         unsigned long long timestamp;
2909         int ret;
2910
2911         ret_if(NULL == tech);
2912         ret_if(NULL == tech->svc_list);
2913         ret_if(NULL == dev_info);
2914
2915         user = tech->device->user;
2916         user->last_seen = tech->last_seen;
2917
2918         for (l = tech->svc_list; NULL != l; l = g_slist_next(l)) {
2919                 uam_db_service_info_t *svc = l->data;
2920                 GSList *l1;
2921                 live_monitoring = FALSE;
2922
2923                 if (!svc || !svc->monitors)
2924                         continue;
2925
2926                 UAM_INFO("service [%s] remaining time [%d] cycle [%d]",
2927                         svc->name, svc->remaining_time, svc->cycle);
2928
2929                 if (!(svc->remaining_time == svc->cycle))
2930                         continue;
2931
2932                 UAM_DBG("Check service device discriminant");
2933                 svc_dev = _uam_core_find_svc_dev_info(dev_info->device_id,
2934                                 dev_info->type, svc->name);
2935                 if (!svc_dev || !svc_dev->discriminant)
2936                         continue;
2937
2938                 UAM_DBG("Send event");
2939                 for (l1 = svc->monitors; NULL != l1; l1 = g_slist_next(l1)) {
2940                         uam_monitor_info_t *mon = l1->data;
2941
2942                         if (!mon)
2943                                 continue;
2944
2945                         if (!(mon->sensors & sensor))
2946                                 continue;
2947
2948                         if (UAM_DETECT_PRESENCE != mon->mode)
2949                                 continue;
2950
2951                         /*
2952                          * For current service, if any of its running monitor has same sensor
2953                          * and detection_mode
2954                          */
2955                         live_monitoring = TRUE;
2956
2957                         timestamp = _uam_get_timestamp();
2958                         UAM_INFO("sensor [%d]", sensor);
2959                         _uam_manager_send_event(mon->name,
2960                                         UAM_EVENT_USER_PRESENCE_DETECTED,
2961                                         g_variant_new("(utsss)", sensor, timestamp,
2962                                                 user->account, svc->name, dev_info->device_id));
2963                         UAM_DBG("Sent UAM_EVENT_USER_PRESENCE_DETECTED to %s"
2964                                         " on device %s"
2965                                         " for 0x%8.8X, User: %s Service: %s Timestamp: %llu",
2966                                         mon->name, dev_info->device_id,
2967                                         sensor, user->account,
2968                                         svc->name,
2969                                         timestamp);
2970                 }
2971
2972                 /* Update service specific device last_seen in svc_dev list and DB */
2973                 if (live_monitoring) {
2974                         svc_dev->last_seen = tech->last_seen;
2975                         ret = _uam_db_update_device_service_last_seen(dev_info->device_id,
2976                                         dev_info->type, dev_info->mac, svc->name, tech->last_seen);
2977                         if (UAM_ERROR_NONE != ret)
2978                                 UAM_WARN("_uam_db_update_device_service_last_seen failed");
2979                 }
2980         }
2981
2982         FUNC_EXIT;
2983 }
2984
2985 int _uam_core_handle_presence_detected(unsigned int sensor,
2986                 int user_id, void *info)
2987 {
2988         FUNC_ENTRY;
2989         int ret = UAM_ERROR_NONE;
2990
2991         GSList *l;
2992         uam_db_user_info_t *user;
2993         uam_db_device_info_t *device;
2994         uam_db_tech_info_t *tech;
2995
2996         uam_device_info_s *dev_info = NULL;
2997         uam_sensor_info_s *sensor_info = NULL;
2998
2999         UAM_INFO("sensor: 0x%8.8X, user_id: %d", sensor, user_id);
3000
3001         if (info && (UAM_SENSOR_BITMASK_LIGHT == sensor || UAM_SENSOR_BITMASK_MOTION == sensor))
3002                 sensor_info = info;
3003         if (info && (UAM_SENSOR_BITMASK_BLE == sensor || UAM_SENSOR_BITMASK_WIFI == sensor))
3004                 dev_info = info;
3005
3006         _uam_vpm_send_presence_detection_event(sensor);
3007
3008         if (NULL == dev_info) {
3009                 __send_sensor_presence_event(sensor_info, sensor);
3010                 return ret;
3011         }
3012
3013         retv_if(0 > user_id, UAM_ERROR_INVALID_PARAMETER);
3014
3015         l = g_slist_find_custom(users, &user_id, __compare_user_id);
3016         if (NULL == l) {
3017                 UAM_ERR("Invalid user_id [%d]", user_id);
3018                 return UAM_ERROR_INVALID_PARAMETER;
3019         }
3020         user = l->data;
3021
3022         l = g_slist_find_custom(user->devices,
3023                         dev_info->device_id, __compare_device_id);
3024         if (NULL == l) {
3025                 UAM_ERR("Valid user_id [%d] but Invalid device_id [%s]",
3026                                 user_id, dev_info->device_id);
3027                 return UAM_ERROR_INVALID_PARAMETER;
3028         }
3029         device = l->data;
3030         if (!(device->supported_techs & dev_info->type)) {
3031                 UAM_ERR("Valid device_id [%s] but Invalid tech type [%d]",
3032                                 dev_info->device_id, dev_info->type);
3033                 return UAM_ERROR_INVALID_PARAMETER;
3034         }
3035
3036         l = g_slist_find_custom(device->tech_list,
3037                         &(dev_info->type), __compare_tech_type);
3038         if (NULL == l) {
3039                 UAM_ERR("Strange, tech type [%d] not found", dev_info->type);
3040                 return UAM_ERROR_INVALID_PARAMETER;
3041         }
3042         tech = l->data;
3043
3044         tech->presence_state = UAM_PRESENCE_STATE_PRESENT;
3045         tech->last_seen = dev_info->last_seen;
3046
3047         retv_if(UAM_ERROR_NONE != __uam_db_begin_transaction(), UAM_ERROR_INVALID_PARAMETER);
3048
3049         /* Check if IP/MAC address was updated then update in DB */
3050         if (UAM_TECH_TYPE_WIFI == dev_info->type) {
3051
3052                 for (l = tech->addresses; NULL != l; l = g_slist_next(l)) {
3053                         uam_db_address_info_t *addr = l->data;
3054
3055                         if (NULL == addr)
3056                                 continue;
3057
3058                         if (UAM_ADDR_TYPE_IPv4 == addr->addr_type) {
3059
3060                                 if (strcasecmp(addr->address, dev_info->ipv4_addr)) {
3061                                         UAM_DBG("Old IPv4: %s, New IPv4: %s",
3062                                                 addr->address, dev_info->ipv4_addr);
3063
3064                                         g_free(addr->address);
3065                                         addr->addr_type = UAM_ADDR_TYPE_IPv4;
3066                                         addr->address = g_strdup(dev_info->ipv4_addr);
3067
3068                                         /* Update IP address in DB */
3069                                         ret = _uam_device_db_update_device_ip_address(dev_info->device_id,
3070                                                         dev_info->type, dev_info->ipv4_addr);
3071                                         if (UAM_ERROR_NONE != ret) {
3072                                                 UAM_WARN("_uam_device_db_update_device_ip_address failed");
3073                                                 __uam_db_end_transaction(0);
3074                                                 return ret;
3075                                         }
3076                                 }
3077                         }
3078
3079                         if (UAM_ADDR_TYPE_WIFI == addr->addr_type) {
3080
3081                                 if (strcasecmp(addr->address, dev_info->mac)) {
3082                                         UAM_DBG("Old MAC: %s, New MAC: %s",
3083                                                 addr->address, dev_info->mac);
3084
3085                                         g_free(addr->address);
3086                                         addr->addr_type = UAM_ADDR_TYPE_WIFI;
3087                                         addr->address = g_strdup(dev_info->mac);
3088
3089                                         /* Update address in DB */
3090                                         ret = _uam_device_db_update_device_mac_address(dev_info->device_id,
3091                                                         dev_info->type, dev_info->mac);
3092                                         if (UAM_ERROR_NONE != ret) {
3093                                                 UAM_WARN("_uam_device_db_update_device_mac_address failed");
3094                                                 __uam_db_end_transaction(0);
3095                                                 return ret;
3096                                         }
3097                                 }
3098                         }
3099                 }
3100         }
3101
3102         /* Update database (presence state & timestamp) */
3103         ret = _uam_device_db_update_device_last_seen(dev_info->device_id,
3104                                 dev_info->type, dev_info->mac, dev_info->last_seen);
3105         if (UAM_ERROR_NONE != ret) {
3106                 UAM_WARN("_uam_device_db_update_device_last_seen failed");
3107                 __uam_db_end_transaction(0);
3108                 return ret;
3109         }
3110
3111         ret = _uam_device_db_update_device_presence(dev_info->device_id,
3112                                 dev_info->type, dev_info->mac, tech->presence_state);
3113         if (UAM_ERROR_NONE != ret) {
3114                 UAM_WARN("_uam_device_db_update_device_presence failed");
3115                 __uam_db_end_transaction(0);
3116                 return ret;
3117         }
3118
3119         /* Send user presence event and update service_device timestamp */
3120         __send_user_presence_event(tech, sensor, dev_info);
3121         __uam_db_end_transaction(1);
3122
3123         FUNC_EXIT;
3124         return ret;
3125 }
3126
3127 static void __send_user_absence_event(uam_tech_type_e type, unsigned int sensor)
3128 {
3129         FUNC_ENTRY;
3130         GSList *l;
3131
3132         /*
3133          * For each service, find users absent on given sensor. Then for each
3134          * monitor in serivce's monitor list, if it is monitoring ABSENCE on
3135          * given sensor, send user ABSENCE event.
3136          */
3137         for (l = services; NULL != l; l = g_slist_next(l)) {
3138                 uam_db_service_info_t *svc = l->data;
3139                 GSList *absent_users = NULL;
3140                 GSList *present_users = NULL;
3141                 GSList *l1;
3142                 GSList *l2;
3143
3144                 if (!svc || !svc->monitors || !svc->dev_techs)
3145                         continue;
3146
3147                 for (l1 = svc->dev_techs; NULL != l1; l1 = g_slist_next(l1)) {
3148                         uam_db_tech_info_t *tech = l1->data;
3149
3150                         if (!tech || (tech->tech_type != type)) {
3151                                 UAM_WARN("tech is NULL or tech->tech_type != type [%d]", type);
3152                                 continue;
3153                         }
3154
3155                         if (!tech->device || !tech->device->user) {
3156                                 UAM_WARN("tech->device is NULL or tech->device->user is NULL");
3157                                 continue;
3158                         }
3159
3160                         l2 = g_slist_find_custom(present_users,
3161                                         &(tech->device->user->user_id), __compare_user_id);
3162
3163                         if (UAM_PRESENCE_STATE_PRESENT == tech->presence_state && tech->discriminant) {
3164                                 UAM_DBG("tech->discriminant [%d] device_id [%s] account [%s]",
3165                                         tech->discriminant,
3166                                         tech->device->device_id,
3167                                         tech->device->user->account);
3168                                 /* Remove user from absent list */
3169                                 absent_users = g_slist_remove(absent_users, tech->device->user);
3170
3171                                 /* If user not in present list, add user to the list */
3172                                 if (!l2) {
3173                                         UAM_DBG("added present user [%s]", tech->device->user->account);
3174                                         present_users = g_slist_prepend(present_users, tech->device->user);
3175                                 }
3176                         } else {
3177                                 /* If user not in the present list then only add it to absent list */
3178                                 if ((NULL == l2) && (NULL == g_slist_find_custom(
3179                                                                 absent_users, &(tech->device->user->user_id),
3180                                                                 __compare_user_id))) {
3181                                         UAM_DBG("added absent user [%s]", tech->device->user->account);
3182                                         absent_users = g_slist_prepend(absent_users, tech->device->user);
3183                                 }
3184                         }
3185                 }
3186
3187                 g_slist_free(present_users);
3188                 if (!absent_users)
3189                         continue;
3190
3191                 for (l2 = svc->monitors; NULL != l2; l2 = g_slist_next(l2)) {
3192                         uam_monitor_info_t *mon = l2->data;
3193
3194                         if (!mon)
3195                                 continue;
3196
3197                         if (!(mon->sensors & sensor))
3198                                 continue;
3199
3200                         if (UAM_DETECT_ABSENCE != mon->mode)
3201                                 continue;
3202
3203                         for (l1 = absent_users; NULL != l1; l1 = g_slist_next(l1)) {
3204                                 uam_db_user_info_t *user = l1->data;
3205
3206                                 if (!user)
3207                                         continue;
3208
3209                                 user->last_seen = 0;
3210
3211                                 _uam_manager_send_event(mon->name,
3212                                                 UAM_EVENT_USER_ABSENCE_DETECTED,
3213                                                 g_variant_new("(utss)", sensor, user->last_seen,
3214                                                         user->account, svc->name));
3215                                 UAM_DBG("Sent UAM_EVENT_USER_ABSENCE_DETECTED to %s"
3216                                                 " for 0x%8.8X, User: %s Service: %s",
3217                                                 mon->name, sensor, user->account, svc->name);
3218                         }
3219                 }
3220
3221                 g_slist_free(absent_users);
3222         }
3223
3224         FUNC_EXIT;
3225 }
3226
3227 void _uam_core_handle_absence_detected(unsigned int sensor,
3228                 int user_id, void *info)
3229 {
3230         FUNC_ENTRY;
3231         uam_db_user_info_t *user;
3232         uam_db_device_info_t *device;
3233         uam_db_tech_info_t *tech;
3234         GSList *l;
3235         uam_device_info_s *dev_info = NULL;
3236         uam_sensor_info_s *sensor_info = NULL;
3237
3238         UAM_INFO("sensor: 0x%8.8X, user_id: %d", sensor, user_id);
3239
3240         if (info && (UAM_SENSOR_BITMASK_LIGHT == sensor || UAM_SENSOR_BITMASK_MOTION == sensor))
3241                 sensor_info = info;
3242         if (info && (UAM_SENSOR_BITMASK_BLE == sensor || UAM_SENSOR_BITMASK_WIFI == sensor))
3243                 dev_info = info;
3244
3245         if (NULL == dev_info) {
3246                 __send_sensor_absence_event(sensor_info, sensor);
3247                 FUNC_EXIT;
3248                 return;
3249         }
3250
3251         ret_if(0 > user_id);
3252
3253         l = g_slist_find_custom(users, &user_id, __compare_user_id);
3254         if (NULL == l) {
3255                 UAM_ERR("Invalid user_id [%d]", user_id);
3256                 return;
3257         }
3258         user = l->data;
3259
3260         l = g_slist_find_custom(user->devices,
3261                         dev_info->device_id, __compare_device_id);
3262         if (NULL == l) {
3263                 UAM_ERR("Valid user_id [%d] but Invalid device_id [%s]",
3264                                 user_id, dev_info->device_id);
3265                 return;
3266         }
3267         device = l->data;
3268         if (!(device->supported_techs & dev_info->type)) {
3269                 UAM_ERR("Valid device_id [%s] but Invalid tech type [%d]",
3270                                 dev_info->device_id, dev_info->type);
3271                 return;
3272         }
3273
3274         l = g_slist_find_custom(device->tech_list,
3275                         &(dev_info->type), __compare_tech_type);
3276         if (NULL == l) {
3277                 UAM_ERR("Strange, tech type [%d] not found", dev_info->type);
3278                 return;
3279         }
3280         tech = l->data;
3281
3282         tech->presence_state = UAM_PRESENCE_STATE_ABSENT;
3283
3284         /* Update database (presence state) */
3285         if (UAM_ERROR_NONE != _uam_device_db_update_device_presence(dev_info->device_id,
3286                                 dev_info->type, dev_info->mac, tech->presence_state))
3287                 UAM_WARN("_uam_device_db_update_device_presence failed");
3288
3289         FUNC_EXIT;
3290 }
3291
3292 void _uam_core_cleanup_monitor(char *name)
3293 {
3294         GSList *l;
3295
3296         for (l = monitors; NULL != l; l = g_slist_next(l)) {
3297                 uam_monitor_info_t *monitor = l->data;
3298
3299                 if (!monitor || !monitor->name || !monitor->service)
3300                         continue;
3301
3302                 if (0 != g_strcmp0(name, monitor->name))
3303                         continue;
3304
3305                 /* If there is a monitor that is not freed, stop detection
3306                  * and free the monitor structure in the memory. */
3307                 UAM_INFO("clear %s's monitor info.", monitor->name);
3308                 __uam_core_stop_detection(monitor->mode,
3309                         monitor->service->name, name, monitor->sensors);
3310         }
3311 }
3312
3313 static void __free_user_info(gpointer data)
3314 {
3315         FUNC_ENTRY;
3316         uam_db_user_info_t *user = data;
3317
3318         ret_if(NULL == user);
3319
3320         g_free(user->name);
3321         g_free(user->account);
3322         g_free(user);
3323         FUNC_EXIT;
3324 }
3325
3326 static void __free_service_info(gpointer data)
3327 {
3328         FUNC_ENTRY;
3329         uam_db_service_info_t *svc = data;
3330
3331         ret_if(NULL == svc);
3332
3333         g_free(svc->name);
3334         g_free(svc);
3335         FUNC_EXIT;
3336 }
3337
3338 static void __free_monitor_info(gpointer data)
3339 {
3340         FUNC_ENTRY;
3341         uam_monitor_info_t *monitor = data;
3342
3343         ret_if(NULL == monitor);
3344
3345         g_free(monitor->name);
3346         g_free(monitor);
3347         FUNC_EXIT;
3348 }
3349
3350 static void __free_scanner_info(gpointer data)
3351 {
3352         FUNC_ENTRY;
3353         uam_scanner_info_t *scanner = data;
3354
3355         ret_if(NULL == scanner);
3356
3357         g_free(scanner->name);
3358         g_free(scanner);
3359         FUNC_EXIT;
3360 }
3361
3362 void _uam_core_reset_database(void)
3363 {
3364         FUNC_ENTRY;
3365         int ret;
3366
3367         ret = _uam_db_clear();
3368         if (UAM_ERROR_NONE != ret) {
3369                 UAM_ERR("_uam_db_clear failed with %s",
3370                                 _uam_manager_error_to_str(ret));
3371                 unlink(DATABASE_FULL_PATH);
3372                 return;
3373         }
3374
3375         g_slist_free_full(devices, __free_user_device);
3376         devices = NULL;
3377
3378         g_slist_free_full(users, __free_user_info);
3379         users = NULL;
3380
3381         g_slist_free_full(services, __free_service_info);
3382         services = NULL;
3383
3384         g_slist_free_full(monitors, __free_monitor_info);
3385         monitors = NULL;
3386
3387         g_slist_free_full(scanners, __free_scanner_info);
3388         scanners = NULL;
3389
3390         /* Set/update registered device list to plugins */
3391         ret = _uam_pm_set_registered_devices(devices);
3392         if (UAM_ERROR_NONE != ret)
3393                 UAM_ERR("_uam_pm_set_registered_devices failed with %s",
3394                                 _uam_manager_error_to_str(ret));
3395
3396         /* Set/update registered device list to cloud plugin */
3397         _uam_cloud_update_registered_devices();
3398
3399         FUNC_EXIT;
3400 }
3401
3402 void _uam_core_handle_detection_started(unsigned int sensor)
3403 {
3404         FUNC_ENTRY;
3405         unsigned int active_sensors = 0;
3406
3407         UAM_DBG("Sensor: 0x%8.8X, detecting_sensors: 0x%8.8X",
3408                         sensor, detecting_sensors);
3409
3410         detecting_sensors |= sensor;
3411         active_sensors |= _uam_core_get_active_sensors(UAM_DETECT_PRESENCE);
3412         active_sensors |= _uam_core_get_active_sensors(UAM_DETECT_ABSENCE);
3413         if (active_sensors == detecting_sensors) {
3414                 /* Send detection started event */
3415                 _uam_manager_send_event(NULL, UAM_EVENT_DETECTION_STARTED, NULL);
3416         }
3417
3418         FUNC_EXIT;
3419 }
3420
3421 void _uam_core_handle_detection_stopped(unsigned int sensor)
3422 {
3423         FUNC_ENTRY;
3424
3425         uam_tech_type_e type = UAM_TECH_TYPE_NONE;
3426         uam_cycle_state_e cycle_state;
3427         GSList *l = NULL;
3428
3429         ret_if((detecting_sensors & sensor) == 0);
3430         UAM_DBG("Sensor: 0x%8.8X, detecting_sensors: 0x%8.8X",
3431                         sensor, detecting_sensors);
3432         detecting_sensors &= ~sensor;
3433
3434         if (UAM_SENSOR_BITMASK_BLE == sensor)
3435                 type = UAM_TECH_TYPE_BLE;
3436         else if (UAM_SENSOR_BITMASK_WIFI == sensor)
3437                 type = UAM_TECH_TYPE_WIFI;
3438
3439         if (UAM_TECH_TYPE_NONE != type)
3440                 __send_user_absence_event(type, sensor);
3441
3442         if (0 == detecting_sensors) {
3443                 /* Send detection stopped event */
3444                 for (l = monitors; l; l = g_slist_next(l)) {
3445                         uam_monitor_info_t *mon = l->data;
3446
3447                         if (!mon || !mon->name || !mon->service)
3448                                 continue;
3449                         uam_db_service_info_t *service = mon->service;
3450                         cycle_state = UAM_DETECTION_CYCLE_END;
3451
3452                         UAM_DBG("mon->sensors[0x%X], [%s]->remaining_time: %d", mon->sensors, service->name, service->remaining_time);
3453                         if (!(mon->sensors & _uam_core_get_env_sensors())) {
3454                                 if (service->remaining_time < service->cycle) {
3455                                         UAM_DBG("service->remaining_time < service->cycle, return");
3456                                         return;
3457                                 }
3458                         } else if (service->remaining_time > UAM_DETECTION_CYCLE_MIN) {
3459                                 cycle_state = UAM_DETECTION_CYCLE_MID;
3460                         }
3461
3462                         _uam_manager_send_event(mon->name, UAM_EVENT_DETECTION_STOPPED,
3463                                         g_variant_new("(si)", service->name, cycle_state));
3464                         UAM_DBG("Sent UAM_EVENT_DETECTION_STOPPED to %s, Service: %s,"
3465                                         " cycle state:[%s]",
3466                                         mon->name, service->name, cycle_state ? "end" : "mid");
3467                 }
3468         }
3469         FUNC_EXIT;
3470 }
3471
3472 static uam_scanner_info_t *__uam_find_scanner(const char *name)
3473 {
3474         GSList *l;
3475
3476         retv_if(NULL == name, NULL);
3477
3478         for (l = scanners; NULL != l; l = g_slist_next(l)) {
3479                 uam_scanner_info_t *scanner = l->data;
3480
3481                 if (!scanner || !scanner->name)
3482                         continue;
3483
3484                 if (0 == g_strcmp0(scanner->name, name)) {
3485                         UAM_DBG("Scanning application found in list");
3486                         return scanner;
3487                 }
3488         }
3489
3490         return NULL;
3491 }
3492
3493 static gboolean __scan_completed_cb(gpointer data)
3494 {
3495         FUNC_ENTRY;
3496         uam_scanner_info_t *scanner = data;
3497
3498         retv_if(NULL == scanner, FALSE);
3499
3500         if (UAM_ERROR_NONE != _uam_manager_send_event(
3501                                 scanner->name, UAM_EVENT_SCAN_COMPLETED, NULL))
3502                 UAM_ERR("Failed to send UAM_EVENT_SCAN_COMPLETED");
3503         else
3504                 UAM_INFO_C("Sent UAM_EVENT_SCAN_COMPLETED to [%s]", scanner->name);
3505
3506         /* Free scanner */
3507         scanners = g_slist_remove(scanners, scanner);
3508         g_free(scanner->name);
3509         g_free(scanner);
3510
3511         FUNC_EXIT;
3512         return FALSE;
3513 }
3514
3515 int _uam_core_start_active_device_scan(char *sender, unsigned int sensors, int detection_period)
3516 {
3517         FUNC_ENTRY;
3518         int ret;
3519         uam_scanner_info_t *scanner;
3520
3521         retv_if(NULL == sender, UAM_ERROR_INVALID_PARAMETER);
3522         retv_if(0 == sensors, UAM_ERROR_INVALID_PARAMETER);
3523
3524         scanner = __uam_find_scanner(sender);
3525         retv_if(NULL != scanner, UAM_ERROR_NOW_IN_PROGRESS);
3526
3527         ret = _uam_pm_start_active_device_scan(&sensors, detection_period);
3528         if (UAM_ERROR_NONE != ret) {
3529                 UAM_ERR("Failed with error: %s (0x%4.4X)",
3530                                 _uam_manager_error_to_str(ret), ret);
3531                 return ret;
3532         }
3533
3534         scanner = g_malloc0(sizeof(uam_scanner_info_t));
3535         if (!scanner) {
3536                 UAM_ERR("Failed to allocate memory");
3537                 return UAM_ERROR_OUT_OF_MEMORY;
3538         }
3539         scanner->name = g_strdup(sender);
3540         scanner->sensors |= sensors;
3541         scanner->timer = g_timeout_add_seconds(detection_period,
3542                         __scan_completed_cb, scanner);
3543         scanners = g_slist_append(scanners, scanner);
3544         UAM_DBG("sensors = 0x%8.8X - 0x%8.8X", scanner->sensors, sensors);
3545
3546         FUNC_EXIT;
3547         return UAM_ERROR_NONE;
3548 }
3549
3550 int _uam_core_stop_active_device_scan(char *sender, unsigned int sensors)
3551 {
3552         FUNC_ENTRY;
3553         int ret;
3554         uam_scanner_info_t *scanner;
3555         GSList *l;
3556
3557         retv_if(NULL == sender, UAM_ERROR_INVALID_PARAMETER);
3558         retv_if(0 == sensors, UAM_ERROR_INVALID_PARAMETER);
3559
3560         scanner = __uam_find_scanner(sender);
3561         retv_if(NULL == scanner, UAM_ERROR_NOT_IN_OPERATION);
3562
3563         /* Trim sensors to a subset of active sensors for the scanner */
3564         sensors &= scanner->sensors;
3565
3566         /*
3567          * modify scanner's active sensors and if active sensors are NULL
3568          * remove scanner from scanners list
3569          */
3570         scanner->sensors &= ~sensors;
3571         if (0 == scanner->sensors) {
3572                 scanners = g_slist_remove(scanners, scanner);
3573                 g_source_remove(scanner->timer);
3574                 g_free(scanner->name);
3575                 g_free(scanner);
3576         }
3577
3578         for (l = scanners; NULL != l; l = g_slist_next(l)) {
3579                 uam_scanner_info_t *scanner_data = l->data;
3580
3581                 if (!scanner_data || !scanner_data->name)
3582                         continue;
3583
3584                 sensors &= ~(scanner_data->sensors);
3585         }
3586
3587         if (0 != sensors) {
3588                 ret = _uam_pm_stop_active_device_scan(sensors);
3589                 if (UAM_ERROR_NONE != ret) {
3590                         UAM_ERR("Failed with error: %s (0x%4.4X)",
3591                                         _uam_manager_error_to_str(ret), ret);
3592                         return ret;
3593                 }
3594         }
3595
3596         FUNC_EXIT;
3597         return UAM_ERROR_NONE;
3598 }
3599
3600 void _uam_core_handle_active_device(uam_active_scan_event_e event,
3601                 unsigned int sensor, const uam_device_info_s *dev_info)
3602 {
3603         FUNC_ENTRY;
3604         GSList *l;
3605
3606         ret_if((UAM_ACTIVE_SCAN_COMPLETED != event) && (NULL == dev_info));
3607
3608         for (l = scanners; NULL != l;) {
3609                 uam_scanner_info_t *scanner = l->data;
3610
3611                 if (!scanner || !scanner->name) {
3612                         l = g_slist_next(l);
3613                         continue;
3614                 }
3615
3616                 if (0 == (scanner->sensors & sensor)) {
3617                         l = g_slist_next(l);
3618                         continue;
3619                 }
3620
3621                 if (event == UAM_ACTIVE_SCAN_COMPLETED) {
3622                         scanner->sensors &= ~(sensor);
3623                         UAM_DBG("sensors = 0x%8.8X", scanner->sensors);
3624                         if (0 != scanner->sensors) {
3625                                 l = g_slist_next(l);
3626                                 continue;
3627                         }
3628
3629                         if (UAM_ERROR_NONE != _uam_manager_send_event(
3630                                                 scanner->name, UAM_EVENT_SCAN_COMPLETED, NULL))
3631                                 UAM_ERR("Failed to send UAM_EVENT_SCAN_COMPLETED");
3632                         else
3633                                 UAM_INFO_C("Sent UAM_EVENT_SCAN_COMPLETED to [%s]", scanner->name);
3634
3635                         /* Free scanner */
3636                         l = g_slist_next(l);
3637                         scanners = g_slist_remove(scanners, scanner);
3638                         g_source_remove(scanner->timer);
3639                         g_free(scanner->name);
3640                         g_free(scanner);
3641                 } else {
3642                         GVariant *param = g_variant_new("(iiisss)",
3643                                         UAM_ERROR_NONE,
3644                                         dev_info->operating_system,
3645                                         dev_info->type,
3646                                         dev_info->mac,
3647                                         dev_info->ipv4_addr,
3648                                         dev_info->device_id);
3649                         if (UAM_ERROR_NONE != _uam_manager_send_event(
3650                                                 scanner->name, UAM_EVENT_DEVICE_FOUND, param))
3651                                 UAM_ERR("Failed to send %s", _uam_manager_event_to_str(event));
3652                         else
3653                                 UAM_INFO_C("Sent UAM_EVENT_DEVICE_FOUND to [%s]", scanner->name);
3654
3655                         l = g_slist_next(l);
3656                 }
3657         }
3658
3659         FUNC_EXIT;
3660 }
3661
3662 int _uam_core_register_service(uam_service_info_s *svc)
3663 {
3664         FUNC_ENTRY;
3665         GSList *l;
3666         uam_db_service_info_t *service;
3667         int service_number = 0;
3668
3669         retv_if(NULL == svc->name, UAM_ERROR_INVALID_PARAMETER);
3670
3671         /* Retrieve service from list */
3672         l = g_slist_find_custom(services, svc->name, __compare_svc_name);
3673         retv_if((NULL != l) && (l->data != NULL), UAM_ERROR_ALREADY_REGISTERED);
3674
3675         service = g_new0(uam_db_service_info_t, 1);
3676         service->name = g_strdup(svc->name);
3677         service->cycle = UAM_DETECTION_CYCLE_DEFAULT;
3678         service->presence_threshold = svc->presence_threshold;
3679         service->absence_threshold = svc->absence_threshold;
3680
3681         /* Add service to database */
3682         if (UAM_ERROR_NONE != _uam_db_insert_service_info(&service_number, svc, service->cycle)) {
3683                 UAM_ERR("_uam_db_insert_service_info failed");
3684                 g_free(service);
3685                 return UAM_ERROR_DB_FAILED;
3686         }
3687
3688         services = g_slist_append(services, service);
3689
3690         /* Send service registered event to application */
3691         if (UAM_ERROR_NONE != _uam_manager_send_event(NULL,
3692                                 UAM_EVENT_SERVICE_REGISTERED, g_variant_new("(is)",
3693                                         UAM_ERROR_NONE, service->name)))
3694                 UAM_ERR("Failed to send UAM_EVENT_SERVICE_REGISTERED");
3695
3696         FUNC_EXIT;
3697         return UAM_ERROR_NONE;
3698 }
3699
3700 int _uam_core_update_service(uam_service_info_s *svc)
3701 {
3702         FUNC_ENTRY;
3703         GSList *l;
3704         uam_db_service_info_t *service;
3705
3706         retv_if(NULL == svc->name, UAM_ERROR_INVALID_PARAMETER);
3707
3708         /* Retrieve service from list */
3709         l = g_slist_find_custom(services, svc->name, __compare_svc_name);
3710         retv_if((NULL == l) || (l->data == NULL), UAM_ERROR_NOT_REGISTERED);
3711
3712         service = l->data;
3713         service->presence_threshold = svc->presence_threshold;
3714         service->absence_threshold = svc->absence_threshold;
3715
3716         /* Update service to database */
3717         if (UAM_ERROR_NONE != _uam_db_update_service_info(service)) {
3718                 UAM_ERR("_uam_db_update_service_info failed");
3719                 return UAM_ERROR_DB_FAILED;
3720         }
3721
3722         FUNC_EXIT;
3723         return UAM_ERROR_NONE;
3724 }
3725
3726 int _uam_core_get_default_service(uam_service_info_s *service_info)
3727 {
3728         FUNC_ENTRY;
3729         int ret;
3730         GSList *l;
3731         uam_db_service_info_t *service;
3732
3733         retv_if(NULL == service_info, UAM_ERROR_INVALID_PARAMETER);
3734
3735         l = g_slist_find_custom(services, UAM_SERVICE_DEFAULT, __compare_svc_name);
3736
3737         if (NULL == l) {
3738                 // insert default service
3739                 memset(service_info, 0x00, sizeof(uam_service_info_s));
3740                 g_strlcpy(service_info->name, UAM_SERVICE_DEFAULT, UAM_SERVICE_MAX_STRING_LEN);
3741                 service_info->presence_threshold = UAM_PRESENCE_THRESHOLD_DEFAULT;
3742                 service_info->absence_threshold = UAM_ABSENCE_THRESHOLD_DEFAULT;
3743
3744                 ret = _uam_core_register_service(service_info);
3745                 if ((UAM_ERROR_NONE != ret) && (UAM_ERROR_ALREADY_REGISTERED != ret)) {
3746                         UAM_ERR("_uam_core_register_service failed with %s", _uam_manager_error_to_str(ret));
3747                         return ret;
3748                 }
3749                 l = g_slist_find_custom(services, UAM_SERVICE_DEFAULT, __compare_svc_name);
3750         }
3751
3752         retv_if(NULL == l, UAM_ERROR_INTERNAL);
3753         service = l->data;
3754
3755         memset(service_info, 0x00, sizeof(uam_service_info_s));
3756         g_strlcpy(service_info->name, service->name, UAM_SERVICE_MAX_STRING_LEN);
3757
3758         FUNC_EXIT;
3759         return UAM_ERROR_NONE;
3760 }
3761
3762 int _uam_core_unregister_service(const char *svc_name)
3763 {
3764         FUNC_ENTRY;
3765         GSList *l;
3766         uam_db_service_info_t *service;
3767
3768         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
3769
3770         /* Retrieve service from list */
3771         l = g_slist_find_custom(services, svc_name, __compare_svc_name);
3772         retv_if((NULL == l), UAM_ERROR_NOT_REGISTERED);
3773         service = l->data;
3774
3775         /* Check if service is being used*/
3776         if (service->monitors) {
3777                 UAM_ERR("service monitoring in progress");
3778                 return UAM_ERROR_PERMISSION_DENIED;
3779         }
3780
3781         /* Remove service from database */
3782         if (UAM_ERROR_NONE != _uam_db_delete_service_info(service->name)) {
3783                 UAM_ERR("_uam_db_delete_service_info failed");
3784                 return UAM_ERROR_DB_FAILED;
3785         }
3786
3787         /* Remove service mapping from devices*/
3788         for (l = service->dev_techs; NULL != l; l = g_slist_next(l)) {
3789                 uam_db_tech_info_t *tech = l->data;
3790                 if (!tech || !tech->addresses)
3791                         continue;
3792                 tech->svc_list = g_slist_remove(tech->svc_list, service);
3793         }
3794         services = g_slist_remove(services, service);
3795
3796         /* Send service unregistered event to application */
3797         if (UAM_ERROR_NONE != _uam_manager_send_event(NULL,
3798                                 UAM_EVENT_SERVICE_UNREGISTERED, g_variant_new("(is)",
3799                                         UAM_ERROR_NONE, service->name)))
3800                 UAM_ERR("Failed to send UAM_EVENT_SERVICE_UNREGISTERED");
3801
3802         FUNC_EXIT;
3803         return UAM_ERROR_NONE;
3804 }
3805
3806 static int __get_service_dev_list(
3807                 uam_db_service_info_t* service, uam_device_info_s **device_list, int *count)
3808 {
3809         FUNC_ENTRY;
3810         GSList *l1;
3811         GSList *s;
3812         int indx = 0;
3813         int ret = UAM_ERROR_NONE;
3814         uam_svc_dev_info_t *svc_dev = NULL;
3815         uam_device_info_s *dev = NULL;
3816
3817         *count = 0;
3818         /* Calculate number of devices */
3819         for (l1 = service->dev_techs; NULL != l1; l1 = g_slist_next(l1)) {
3820                 uam_db_tech_info_t *tech = l1->data;
3821                 if (!tech || !tech->addresses)
3822                         continue;
3823
3824                 (*count)++;
3825         }
3826
3827         *device_list = g_new0(uam_device_info_s, *count);
3828
3829         /* Copy devices */
3830         for (l1 = service->dev_techs; NULL != l1; l1 = g_slist_next(l1)) {
3831                 uam_db_tech_info_t *tech = l1->data;
3832
3833                 if (!tech || !tech->addresses)
3834                         continue;
3835
3836                 /* Copy tech info to device info */
3837                 ret = __copy_tech_info_to_device_info(tech, &((*device_list)[indx]));
3838                 if (UAM_ERROR_NONE != ret) {
3839                         UAM_ERR("__copy_tech_info_to_device_info failed");
3840                         return ret;
3841                 }
3842
3843                 (*device_list)[indx].last_seen = 0;
3844                 indx++;
3845         }
3846
3847         UAM_INFO("Count = %d, indx = %d", *count, indx);
3848
3849         /* Update service specific device last time */
3850         for (s = svc_devs; s; s = g_slist_next(s)) {
3851                 svc_dev = s->data;
3852
3853                 if (!svc_dev || !svc_dev->device_id || !svc_dev->service)
3854                         continue;
3855                 if (g_strcmp0(svc_dev->service, service->name))
3856                         continue;
3857
3858                 for (indx = 0; indx < *count; indx++) {
3859                         dev = &((*device_list)[indx]);
3860
3861                         if (svc_dev->tech_type != dev->type ||
3862                                         g_strcmp0(svc_dev->device_id, dev->device_id))
3863                                 continue;
3864
3865                         dev->last_seen = svc_dev->last_seen;
3866                 }
3867         }
3868
3869         FUNC_EXIT;
3870         return ret;
3871 }
3872
3873 int _uam_core_get_service_devices(const char *svc_name,
3874                 int *count, uam_device_info_s **device_list)
3875 {
3876         FUNC_ENTRY;
3877         uam_db_service_info_t *service;
3878         GSList *l;
3879         int ret = UAM_ERROR_NONE;
3880
3881         l = g_slist_find_custom(services, svc_name, __compare_svc_name);
3882         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
3883         service = l->data;
3884
3885         ret = __get_service_dev_list(service, device_list, count);
3886
3887         FUNC_EXIT;
3888         return ret;
3889 }
3890
3891 static void __get_service_user_list(
3892                 uam_db_service_info_t* service, uam_user_info_s **user_list, int *count)
3893 {
3894         FUNC_ENTRY;
3895         GSList *l;
3896         int indx = 0;
3897         GSList *svc_user_list = NULL;
3898
3899         *count = 0;
3900         /* Calculate number of users */
3901         for (l = service->dev_techs; NULL != l; l = g_slist_next(l)) {
3902                 uam_db_tech_info_t *tech = l->data;
3903                 if (!tech || !tech->addresses)
3904                         continue;
3905
3906                 GSList *l1;
3907                 uam_db_user_info_t *db_info = tech->device->user;
3908                 l1 = g_slist_find_custom(svc_user_list , db_info->account, __compare_user_account);
3909                 if (NULL == l1)
3910                         svc_user_list = g_slist_append(svc_user_list, db_info);
3911         }
3912
3913         *count = g_slist_length(svc_user_list);
3914         *user_list = g_new0(uam_user_info_s, *count);
3915
3916         /* Copy users */
3917         for (l = svc_user_list; l; l = g_slist_next(l)) {
3918                 uam_db_user_info_t *db_info = l->data;
3919
3920                 if (!db_info || !db_info->account)
3921                         continue;
3922
3923                 g_strlcpy((*user_list)[indx].account,
3924                                 db_info->account, UAM_USER_ACCOUNT_MAX_STRING_LEN);
3925                 if (db_info->name)
3926                         g_strlcpy((*user_list)[indx].name,
3927                                         db_info->name, UAM_USER_NAME_MAX_STRING_LEN);
3928
3929                 indx += 1;
3930         }
3931
3932         UAM_INFO("Count = %d, indx = %d", *count, indx);
3933         FUNC_EXIT;
3934 }
3935
3936 int _uam_core_get_service_users(const char *svc_name,
3937                 int *count, uam_user_info_s **user_list)
3938 {
3939         FUNC_ENTRY;
3940         uam_db_service_info_t *service;
3941         GSList *l;
3942
3943         l = g_slist_find_custom(services, svc_name, __compare_svc_name);
3944         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
3945         service = l->data;
3946
3947         __get_service_user_list(service, user_list, count);
3948
3949         FUNC_EXIT;
3950         return UAM_ERROR_NONE;
3951 }
3952
3953 int _uam_core_get_services(int *count, uam_service_info_s **service_list)
3954 {
3955         FUNC_ENTRY;
3956         guint size;
3957         GSList *l;
3958
3959         size = g_slist_length(services);
3960         *service_list = g_new0(uam_service_info_s, size);
3961         *count = 0;
3962
3963         /* fetch services list from DB */
3964         for (l = services; l; l = g_slist_next(l)) {
3965                 uam_db_service_info_t *db_info = l->data;
3966
3967                 if (!db_info || !db_info->name)
3968                         continue;
3969
3970                 g_strlcpy((*service_list)[*count].name,
3971                                 db_info->name, UAM_SERVICE_MAX_STRING_LEN);
3972                 (*service_list)[*count].presence_threshold = db_info->presence_threshold;
3973                 (*service_list)[*count].absence_threshold = db_info->absence_threshold;
3974                 *count += 1;
3975         }
3976
3977         UAM_INFO("Count: %d", *count);
3978         FUNC_EXIT;
3979         return UAM_ERROR_NONE;
3980 }
3981
3982 int _uam_core_add_ibeacon_adv(unsigned int adv_len, const char *iadv)
3983 {
3984         FUNC_ENTRY;
3985         int ret;
3986
3987         UAM_INFO("adv_len = %u, iadv = 0x%0x:0x%0x:0x%0x", adv_len,
3988                 iadv[0], iadv[1], iadv[2]);
3989
3990         ret = _uam_db_insert_adv_info(adv_len, iadv);
3991         if (UAM_ERROR_NONE != ret) {
3992                 UAM_ERR("_uam_db_insert_adv_info failed");
3993                 return ret;
3994         }
3995
3996         ret = _uam_pm_add_ibeacon_adv(adv_len, iadv);
3997         if (UAM_ERROR_NONE != ret) {
3998                 UAM_ERR("Failed with error: %s (0x%4.4X)",
3999                                 _uam_manager_error_to_str(ret), ret);
4000                 return ret;
4001         }
4002
4003         FUNC_EXIT;
4004         return UAM_ERROR_NONE;
4005 }
4006
4007 void _uam_core_handle_status_changed(unsigned int sensor, void *info)
4008 {
4009         FUNC_ENTRY;
4010
4011         uam_sensor_info_s *sensor_info = info;
4012
4013         ret_if(NULL == info);
4014
4015         UAM_DBG("%d %d %llu %d %d", sensor, sensor_info->status, sensor_info->timestamp,
4016                 sensor_info->accuracy, sensor_info->count);
4017
4018         UAM_INFO("sensor: 0x%8.8X %s", sensor, sensor_info->status == UAS_ABSENCE ?
4019                 "UAM_EVENT_ABSENCE_DETECTED" : "UAM_EVENT_PRESENCE_DETECTED");
4020
4021         _uam_manager_send_event(NULL, UAM_EVENT_SENSOR_STATUS_CHANGED,
4022                 g_variant_new("(uutiidddd)", sensor, sensor_info->status, sensor_info->timestamp,
4023                 sensor_info->accuracy, sensor_info->count, sensor_info->values[0],
4024                 sensor_info->values[1], sensor_info->values[2], sensor_info->values[3]));
4025
4026         FUNC_EXIT;
4027 }
4028
4029 int _uam_core_add_payload(uam_ble_payload_s *payload,
4030                 const char *device_id, int tech_type)
4031 {
4032         FUNC_ENTRY;
4033         int ret = UAM_ERROR_NONE;
4034         uam_db_tech_info_t *tech_info;
4035         uam_db_payload_info_t *db_payload = g_new0(uam_db_payload_info_t, 1);
4036         char *mac;
4037
4038         retv_if(NULL == payload, UAM_ERROR_INVALID_PARAMETER);
4039         retv_if(NULL == device_id, UAM_ERROR_INVALID_PARAMETER);
4040         retv_if(UAM_TECH_TYPE_NONE >= tech_type, UAM_ERROR_INVALID_PARAMETER);
4041         retv_if(UAM_TECH_TYPE_MAX <= tech_type, UAM_ERROR_INVALID_PARAMETER);
4042
4043         // <TO-DO> check if payload already exist
4044
4045         tech_info = __uam_core_get_dev_tech_info(device_id, tech_type);
4046         retv_if(NULL == tech_info, UAM_ERROR_INVALID_PARAMETER);
4047         mac = __get_mac_addr(tech_info);
4048
4049         __uam_copy_uam_payload_info(db_payload, payload);
4050         db_payload->device_id = g_strdup(device_id);
4051         db_payload->tech_type = tech_type;
4052         payloads = g_slist_append(payloads, db_payload);
4053
4054         /*** Add payload to database ***/
4055         ret = _uam_db_insert_payload_info(device_id, tech_type, mac, payload);
4056         if (UAM_ERROR_NONE != ret) {
4057                 UAM_ERR("_uam_db_insert_payload_info failed");
4058                 return ret;
4059         }
4060
4061         FUNC_EXIT;
4062         return UAM_ERROR_NONE;
4063 }
4064
4065 int _uam_core_service_add_payload(uam_ble_payload_s *payload,
4066                 const char *svc_name)
4067 {
4068         FUNC_ENTRY;
4069         int ret = UAM_ERROR_NONE;
4070         uam_db_service_info_t *service;
4071         uam_db_payload_info_t *db_payload;
4072         uam_svc_dev_info_t *svc_dev;
4073         uam_db_device_info_t *device;
4074         GSList *l;
4075
4076         retv_if(NULL == payload, UAM_ERROR_INVALID_PARAMETER);
4077         retv_if(NULL == svc_name, UAM_ERROR_INVALID_PARAMETER);
4078
4079         /* Retrieve service from list */
4080         l = g_slist_find_custom(services, svc_name, __compare_svc_name);
4081         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
4082         service = l->data;
4083
4084         /* Retrieve payload from list */
4085         l = g_slist_find_custom(payloads, payload, __compare_payload);
4086         retv_if(NULL == l, UAM_ERROR_INVALID_PARAMETER);
4087         db_payload = l->data;
4088
4089         // <TO-DO> check if this device-service pair exist
4090
4091         /**Update svc_dev*/
4092         _uam_core_update_svc_dev_info(db_payload->device_id, db_payload->tech_type,
4093                 service->name, -1, -1, payload);
4094         svc_dev = _uam_core_find_svc_dev_info(db_payload->device_id,
4095                 db_payload->tech_type, service->name);
4096         retv_if(NULL == svc_dev, UAM_ERROR_INVALID_PARAMETER);
4097
4098         /**Update svc_dev list for device*/
4099         l = g_slist_find_custom(devices, db_payload->device_id, __compare_device_id);
4100         device = l->data;
4101
4102         for (l = device->tech_list; NULL != l; l = g_slist_next(l)) {
4103                 uam_db_tech_info_t *tech = l->data;
4104
4105                 if (!tech)
4106                         continue;
4107
4108                 if (db_payload->tech_type != tech->tech_type)
4109                         continue;
4110
4111                 tech->svc_dev_list = g_slist_append(tech->svc_dev_list, svc_dev);
4112         }
4113
4114         /* Set/update registered device list to plugins */
4115         if (UAM_ERROR_NONE != _uam_pm_set_registered_devices(devices))
4116                 UAM_ERR("_uam_pm_set_registered_devices failed");
4117
4118
4119         /*** Add payload service mapping to database ***/
4120         ret = _uam_db_update_device_service_payload_info(payload, service->name);
4121         if (UAM_ERROR_NONE != ret) {
4122                 UAM_ERR("_uam_db_update_device_service_payload_info failed");
4123                 return ret;
4124         }
4125
4126         FUNC_EXIT;
4127         return UAM_ERROR_NONE;
4128 }
4129
4130 int _uam_core_get_payloads(int *count, uam_ble_payload_s **payload_list)
4131 {
4132         FUNC_ENTRY;
4133         guint size;
4134         GSList *l;
4135
4136         size = g_slist_length(payloads);
4137         *payload_list = g_new0(uam_ble_payload_s, size);
4138         *count = 0;
4139
4140         /* fetch payloads list from DB */
4141         for (l = payloads; l; l = g_slist_next(l)) {
4142                 uam_db_payload_info_t *db_info = l->data;
4143
4144                 if (!db_info)
4145                         continue;
4146                 __uam_copy_db_payload_info(&((*payload_list)[*count]), db_info);
4147                 *count += 1;
4148         }
4149
4150         UAM_INFO("Count: %d", *count);
4151         FUNC_EXIT;
4152         return UAM_ERROR_NONE;
4153 }