461b59629cb66505fbec57936f5a4a9f6a77b0de
[platform/core/uifw/capi-ui-sticker.git] / receiver / src / ft.cpp
1 /*
2  * Copyright (c) 2020 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 #include <stdio.h>
18 #include <glib.h>
19 #include <dlog.h>
20 #include <service_app.h>
21 #include <app_common.h>
22 #include <sap.h>
23 #include <sap_file_transfer.h>
24 #include <sticker_provider.h>
25 #include <string.h>
26 #include <string>
27 #include <unistd.h>
28 #include <linux/limits.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <pwd.h>
32 #include <json-glib/json-glib.h>
33 #include <vconf.h>
34 #include <queue>
35 #include <thumbnail_util.h>
36
37 #include "ft.h"
38 #include "log.h"
39 #include "sticker_info.h"
40 #include "../inc/sticker_data.h"
41 #include "sticker_request.h"
42 #include "message.h"
43 #include "sync_alarm.h"
44 #include "config.h"
45
46 #define STICKER_SYNC_FEATURE_REQ "sticker-sync-feature-req"
47 #define STICKER_SYNC_FEATURE_RSP "sticker-sync-feature-rsp"
48 #define STICKER_REQUEST_SYNC_REQ "sticker-request-sync-req"
49 #define STICKER_SYNC_START_REQ "sticker-sync-start-req"
50 #define STICKER_SYNC_START_RSP "sticker-sync-start-rsp"
51 #define STICKER_SEND_START_REQ "sticker-send-start-req"
52 #define STICKER_SEND_START_RSP "sticker-send-start-rsp"
53 #define STICKER_SEND_FACE_DATA "sticker-send-face-data"
54 #define STICKER_SEND_STOP_REQ  "sticker-send-stop-req"
55 #define STICKER_SEND_STOP_RSP  "sticker-send-stop-rsp"
56
57 #ifndef VCONFKEY_STICKER_SYNC_COMPLETE_DONE
58 #define VCONFKEY_STICKER_SYNC_COMPLETE_DONE 0x1
59 #endif
60
61 using namespace std;
62
63 enum {
64     SYNC_START_RSP_SUCCESS = 1000,
65     SYNC_START_RSP_NO_STICKER = 1001
66 };
67
68 struct sap_info_s {
69     sap_agent_h agent;
70     sap_socket_h socket;
71     sap_peer_agent_h peer_agent;
72     sap_file_transaction_h file_socket;
73 };
74
75 static struct sap_info_s priv_data = { 0 };
76 static struct sticker_info sticker_data;
77 static queue<StickerRequest> ReqQueue;
78 static StickerRequest current_request;
79
80 static gboolean file_on_progress = FALSE;
81 static string incoming_file_name;
82 static int t_id = 0;
83 static int rec_file_cnt_in_group = 0;
84 static int total_file_count_in_group = 0;
85 static int sync_success_cnt = 0;
86
87 static void set_first_sync_complete()
88 {
89     int complete_flags = 0;
90     if (vconf_get_int(VCONFKEY_STICKER_SYNC_COMPLETE, &complete_flags) == 0 && complete_flags == 0) {
91         if (vconf_set_int(VCONFKEY_STICKER_SYNC_COMPLETE, VCONFKEY_STICKER_SYNC_COMPLETE_DONE) == 0)
92             LOGD("Succeed to set sync complete");
93         else
94             LOGW("Fail to set sync complete");
95     }
96 }
97
98 static void set_sync_progressing(gboolean flag)
99 {
100 #ifdef VCONFKEY_STICKER_SYNC_STATE
101     LOGD("sync progressing : %d", flag);
102     if (vconf_set_int(VCONFKEY_STICKER_SYNC_STATE, flag ? VCONFKEY_STICKER_SYNC_STATE_IN_PROGRESS :  VCONFKEY_STICKER_SYNC_STATE_WAITING) == 0)
103         LOGD("Succeed to set sync state");
104     else
105         LOGW("Fail to set sync state");
106 #else
107     LOGW("No vconf sync state definition");
108 #endif
109 }
110
111 static gboolean _send_json_data(JsonObject *obj)
112 {
113     JsonGenerator *j_generator = NULL;
114     JsonNode *j_node = NULL;
115     gsize size = 0;
116     gchar *data = NULL;
117     int result = 1;
118
119     j_generator = json_generator_new();
120     if (j_generator == NULL) {
121         LOGE("Unable to json_generator_new");
122         goto cleanup;
123     }
124
125     j_node = json_node_new(JSON_NODE_OBJECT);
126     if (j_node == NULL) {
127         LOGE("Unable to json_node_new");
128         goto cleanup;
129     }
130
131     json_node_set_object(j_node, obj);
132     json_generator_set_root(j_generator, j_node);
133
134     data = json_generator_to_data(j_generator, &size);
135     if (data == NULL) {
136         LOGE("Unable to json_generator_to_data");
137         goto cleanup;
138     }
139
140     if (priv_data.socket) {
141         LOGD("Send JSON data : %s", data);
142         result = sap_socket_send_data(priv_data.socket, ACCESSORY_SERVICE_CHANNEL_ID, strlen(data), (void *)data);
143     }
144
145 cleanup:
146     if (data)
147         g_free(data);
148
149     if (j_node)
150         json_node_free(j_node);
151
152     if (j_generator)
153         g_object_unref(j_generator);
154
155     return result ? FALSE : TRUE;
156 }
157
158 static void notify_sync_progress(unsigned int file_progress)
159 {
160     if (total_file_count_in_group == 0)
161         return;
162
163     LOGI("(%2d / %2d), file progress : %3u%%", rec_file_cnt_in_group+1, total_file_count_in_group, file_progress);
164     send_message("sync_progress", NULL);
165 }
166
167 static void _on_send_completed(sap_file_transaction_h file_transaction,
168                                sap_ft_transfer_e result,
169                                const char *file_path,
170                                void *user_data)
171 {
172     if (priv_data.file_socket) {
173         sap_file_transfer_destroy(file_transaction);
174         priv_data.file_socket = NULL;
175     }
176
177     if (result == SAP_FT_TRANSFER_SUCCESS) {
178         LOGI("Transfer Completed");
179
180         if (chmod(sticker_data.file_path.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
181             LOGE("Failed to change permission : %s. error : %s", sticker_data.file_path.c_str(), strerror(errno));
182         }
183         else {
184             LOGI("Succeed to change permission : %s", sticker_data.file_path.c_str());
185             if (create_sticker_provider_handle() == STICKER_ERROR_NONE) {
186                 char thumb_path[PATH_MAX];
187                 char *data_path = NULL;
188                 data_path = app_get_shared_data_path();
189                 sprintf(thumb_path, "%s/thumbnail/%s", data_path, incoming_file_name.c_str());
190                 sticker_data.thumbnail_path = string(thumb_path);
191
192                 if (data_path)
193                     free(data_path);
194
195                 int ret = thumbnail_util_extract_to_file(sticker_data.file_path.c_str(), THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, sticker_data.thumbnail_path.c_str());
196                 if (ret != THUMBNAIL_UTIL_ERROR_NONE) {
197                     LOGE("Failed to create thumbnail. msg : %s", get_error_message(ret));
198                     sticker_data.thumbnail_path.clear();
199                 } else {
200                     insert_sticker_data(sticker_data.file_path.c_str(), sticker_data.keyword.c_str(), sticker_data.group.c_str(), sticker_data.description.c_str(), sticker_data.thumbnail_path.c_str());
201                     destroy_sticker_provider_handle();
202                 }
203
204                 if (unlink(sticker_data.file_path.c_str()) == -1)
205                     LOGE("Failed to remove sticker file");
206
207                 if (!sticker_data.thumbnail_path.empty()) {
208                     if (unlink(sticker_data.thumbnail_path.c_str()) == -1)
209                         LOGE("Failed to remove sticker thumbnail");
210                 }
211             }
212         }
213
214         rec_file_cnt_in_group++;
215     } else {
216         switch (result) {
217             case (SAP_FT_TRANSFER_FAIL_CHANNEL_IO): {
218                 LOGW("Channel IO Error.");
219                 break;
220             }
221
222             case (SAP_FT_TRANSFER_FAIL_FILE_IO): {
223                 LOGW("File IO Error.");
224                 break;
225             }
226
227             case (SAP_FT_TRANSFER_FAIL_CMD_DROPPED):
228             {
229                 LOGW("Transfer dropped.");
230                 break;
231             }
232
233             case (SAP_FT_TRANSFER_FAIL_PEER_UNRESPONSIVE):
234             {
235                 LOGW("Peer Un Responsive.");
236                 break;
237             }
238
239             case (SAP_FT_TRANSFER_FAIL_PEER_CONN_LOST):
240             {
241                 LOGW("Connection Lost.");
242                 break;
243             }
244
245             case (SAP_FT_TRANSFER_FAIL_PEER_CANCELLED):
246             {
247                 LOGW("Peer Cancelled.");
248                 break;
249             }
250
251             case (SAP_FT_TRANSFER_FAIL_SPACE_NOT_AVAILABLE):
252             {
253                 LOGW("No Space.");
254                 break;
255             }
256
257             default:
258                 LOGW("Unknown Error");
259                 break;
260         }
261     }
262
263     file_on_progress = FALSE;
264     sticker_data.reset();
265 }
266
267 static void _on_sending_file_in_progress(sap_file_transaction_h file_transaction,
268                                          unsigned short int percentage_progress,
269                                          void *user_data)
270 {
271     notify_sync_progress(percentage_progress);
272 }
273
274 static void __set_file_transfer_cb(sap_file_transaction_h file_socket)
275 {
276     LOGI("# set callbacks");
277     sap_file_transfer_set_progress_cb(file_socket, _on_sending_file_in_progress, NULL);
278
279     sap_file_transfer_set_done_cb(file_socket, _on_send_completed, NULL);
280 }
281
282 void accept_file()
283 {
284     int ret;
285     char file_path[PATH_MAX];
286     char *data_path = NULL;
287
288     data_path = app_get_shared_data_path();
289     LOGI("Path : %s", data_path);
290     sprintf(file_path, "%s/%s", data_path, incoming_file_name.c_str());
291     LOGI("Receive filepath : %s", file_path);
292     sticker_data.file_path = string(file_path);
293
294     if (data_path)
295         free(data_path);
296
297     ret = sap_file_transfer_receive(priv_data.file_socket, file_path);
298     switch(ret) {
299         case SAP_RESULT_PERMISSION_DENIED:
300             LOGW("permission denied");
301             break;
302         case SAP_RESULT_FAILURE:
303             LOGW("Fail");
304             break;
305         case SAP_RESULT_SUCCESS:
306             LOGI("Success");
307             break;
308     }
309
310     file_on_progress = TRUE;
311 }
312
313 bool request_sticker_data(const char *mode, const char *category, const char *type)
314 {
315     bool result = false;
316     JsonObject *j_object = NULL;
317
318     if (!priv_data.socket) {
319         StickerRequest pending_request;
320         pending_request.req_type = REQUEST_TYPE_SYNC;
321         pending_request.mode = string(mode ? mode : "manual");
322         pending_request.category = string(category ? category : "arsticker");
323         pending_request.type = string(type ? type : "input");
324
325         ReqQueue.push(pending_request);
326         LOGI("Push sync request");
327
328         return false;
329     }
330
331     j_object = json_object_new();
332     if (j_object == NULL) {
333         LOGE("json object create error");
334         return false;
335     }
336
337     json_object_set_string_member(j_object, "msgId", STICKER_SYNC_START_REQ);
338     json_object_set_int_member(j_object, "tID", ++t_id);
339     json_object_set_string_member(j_object, "mode", mode);
340     json_object_set_string_member(j_object, "category", category);
341     json_object_set_string_member(j_object, "type", type);
342
343     if (_send_json_data(j_object) == FALSE) {
344         LOGE("Failed to send STICKER_SYNC_START_REQ");
345         result = false;
346     }
347     else {
348         current_request.req_type = REQUEST_TYPE_SYNC;
349         current_request.mode = string(mode ? mode : "manual");
350         current_request.category = string(category ? category : "arsticker");
351         current_request.type = string(type ? type : "input");
352         set_sync_progressing(TRUE);
353         result = true;
354     }
355
356     json_object_unref(j_object);
357
358     return result;
359 }
360
361 static int _create_directory(const char *path)
362 {
363     if (access(path, F_OK) == 0)
364         return 0;
365
366     if (mkdir(path, 0755) == -1) {
367         LOGE("directory create error");
368         return -1;
369     }
370
371     return 0;
372 }
373
374 void request_sticker_feature()
375 {
376     JsonObject *j_object = NULL;
377
378     if (!priv_data.socket) {
379         StickerRequest pending_request;
380         pending_request.req_type = REQUEST_TYPE_FEATURE_REQ;
381         ReqQueue.push(pending_request);
382         LOGI("Push sync feature request");
383         return;
384     }
385
386     j_object = json_object_new();
387     if (j_object == NULL) {
388         LOGE("json object create error");
389         return;
390     }
391
392     json_object_set_string_member(j_object, "msgId", STICKER_SYNC_FEATURE_REQ);
393     json_object_set_int_member(j_object, "tID", ++t_id);
394
395     if (_send_json_data(j_object) == FALSE) {
396         LOGE("Failed to send STICKER_SYNC_FEATURE_REQ");
397     }
398
399     json_object_unref(j_object);
400
401     char thumb_path[PATH_MAX];
402     char *data_path = NULL;
403     data_path = app_get_shared_data_path();
404     sprintf(thumb_path, "%s/thumbnail", data_path);
405
406     if (_create_directory(thumb_path) != 0)
407         LOGE("Failed to create thumbnail directory");
408 }
409
410 void reject_file()
411 {
412     int ret = sap_file_transfer_reject(priv_data.file_socket);
413     LOGI("ret : %d", ret);
414
415     file_on_progress = FALSE;
416 }
417
418 static void _on_receive_file_cb(sap_peer_agent_h peer_agent_h,
419                                 sap_file_transaction_h socket,
420                                 const char *file_path,
421                                 void *user_data)
422 {
423     file_on_progress = TRUE;
424     priv_data.file_socket = socket;
425     LOGI("# incoming file request.");
426     __set_file_transfer_cb(priv_data.file_socket);
427
428     incoming_file_name = file_path;
429     std::size_t found = incoming_file_name.find_last_of("/");
430     incoming_file_name = incoming_file_name.substr(found+1);
431
432     LOGI("# file path : %s, incoming file name : %s", file_path, incoming_file_name.c_str());
433
434     accept_file();
435 }
436
437 void conn_terminated(sap_peer_agent_h peer_agent,
438                      sap_socket_h socket,
439                      sap_service_connection_terminated_reason_e result,
440                      void *user_data)
441 {
442     sap_info_s *priv = NULL;
443     priv = (sap_info_s *)user_data;
444
445     switch (result)
446     {
447     case SAP_CONNECTION_TERMINATED_REASON_PEER_DISCONNECTED:
448         LOGW("Peer Disconnected");
449         break;
450     case SAP_CONNECTION_TERMINATED_REASON_DEVICE_DETACHED:
451         LOGW("Disconnected Device Detached");
452         break;
453     case SAP_CONNECTION_TERMINATED_REASON_UNKNOWN:
454         LOGW("Disconnected Unknown Reason");
455         break;
456     default:
457         LOGW("connection terminated. reason : %d", result);
458         break;
459     }
460
461     sap_socket_destroy(priv->socket);
462     priv->socket = NULL;
463
464     set_sync_progressing(FALSE);
465     service_app_exit();
466 }
467
468 static bool process_request_queue()
469 {
470     if (ReqQueue.empty())
471         return false;
472
473     StickerRequest request = ReqQueue.front();
474
475     if (request.req_type == REQUEST_TYPE_FEATURE_REQ) {
476         LOGD("[Request feature exchange]");
477         request_sticker_feature();
478         ReqQueue.pop();
479     }
480     else if (request.req_type == REQUEST_TYPE_SYNC) {
481         LOGD("[Request to sync sticker] mode: %s, category: %s, type : %s", request.mode.c_str(),
482                 request.category.c_str(),
483                 request.type.c_str());
484
485         if (request_sticker_data(request.mode.c_str(), request.category.c_str(), request.type.c_str()))
486             ReqQueue.pop();
487     }
488
489     return true;
490 }
491
492 void
493 on_data_received(sap_socket_h socket, unsigned short int channel_id, unsigned int payload_length, void *buffer,
494                  void *user_data) /* message exchange on_receive callback (sap_agent_data_received_cb) */
495 {
496     unsigned int buf_len = strlen((char *)buffer);
497     LOGI("received data: %s, len: %d, buffer len : %d", (char *)buffer, payload_length, buf_len);
498
499     JsonParser *parser = json_parser_new();
500     GError *err_msg = NULL;
501     JsonNode *root = NULL;
502     JsonObject *root_obj = NULL;
503     string msg_id;
504     const char *json_msgid = NULL;
505
506     json_parser_load_from_data(parser, (char *)buffer, payload_length, &err_msg);
507     if (err_msg) {
508         LOGE("failed to load json file. error message: %s", err_msg->message);
509         goto cleanup;
510     }
511
512     root = json_parser_get_root(parser);
513     if (root == NULL) {
514         LOGE("failed to get root");
515         goto cleanup;
516     }
517
518     root_obj = json_node_get_object(root);
519     if (root_obj == NULL) {
520         LOGE("failed to get object");
521         goto cleanup;
522     }
523
524     json_msgid = json_object_get_string_member(root_obj, "msgId");
525     msg_id = string(json_msgid ? json_msgid : "");
526     if (msg_id == STICKER_REQUEST_SYNC_REQ) {
527         if (!request_sticker_data(current_request.mode.c_str(), current_request.category.c_str(), current_request.type.c_str()))
528             LOGW("Failed to request sticker sync");
529     } else if (msg_id == STICKER_SYNC_FEATURE_RSP) {
530         LOGD("msg : %s", msg_id.c_str());
531 #ifdef VCONFKEY_STICKER_SUPPORTED_FEATURE
532         const char *json_aremoji = json_object_get_string_member(root_obj, "arEmoji");
533         const char *json_bitmoji = json_object_get_string_member(root_obj, "bitmoji");
534         string support_aremoji = string(json_aremoji ? json_aremoji : "");
535         string support_bitmoji = string(json_bitmoji ? json_bitmoji : "");
536         int supported_feature = VCONFKEY_STICKER_FEATURE_NONE;
537
538         if (support_aremoji == "support")
539             supported_feature |= VCONFKEY_STICKER_FEATURE_AREMOJI;
540
541         if (support_bitmoji == "support")
542             supported_feature |= VCONFKEY_STICKER_FEATURE_BITMOJI;
543
544         if (vconf_set_int(VCONFKEY_STICKER_SUPPORTED_FEATURE, supported_feature) == 0)
545             LOGD("Succeed to set supported feature");
546         else
547             LOGW("Fail to set supported feature");
548 #else
549         LOGW("No vconf supported feature");
550 #endif
551
552         if (!process_request_queue()) {
553             service_app_exit();
554         }
555     } else if (msg_id == STICKER_SYNC_START_RSP) {
556         LOGD("msg : %s", msg_id.c_str());
557         const char *json_result = json_object_get_string_member(root_obj, "result");
558         string result = string(json_result ? json_result : "");
559         int result_code = json_object_get_int_member(root_obj, "resultCode");
560         LOGD("result : %s, resultCode : %d", result.c_str(), result_code);
561
562         string response_to_app;
563         switch (result_code) {
564         case SYNC_START_RSP_SUCCESS:
565             response_to_app = "success";
566             break;
567         case SYNC_START_RSP_NO_STICKER:
568             response_to_app = "no_sticker";
569             break;
570         default:
571             response_to_app = "unknown_error";
572             break;
573         }
574
575         send_message("sync_start_response", response_to_app.c_str());
576
577         if (result_code != SYNC_START_RSP_SUCCESS) {
578             set_sync_progressing(FALSE);
579             if (!process_request_queue()) {
580                 service_app_exit();
581             }
582         }
583     } else if (msg_id == STICKER_SEND_START_REQ) {
584         LOGD("msg : %s", msg_id.c_str());
585         total_file_count_in_group = 0;
586         rec_file_cnt_in_group = 0;
587         t_id = json_object_get_int_member(root_obj, "tID");
588         JsonArray *file_list = json_object_get_array_member(root_obj, "list");
589         if (file_list) {
590             int arr_len = json_array_get_length(file_list);
591             for (int i = 0; i < arr_len; i++) {
592                 JsonObject *file_obj = json_array_get_object_element(file_list, i);
593                 int file_len = json_object_get_int_member(file_obj, "size");
594                 const char *json_filename = json_object_get_string_member(file_obj, "fileName");
595                 string file_name = string(json_filename ? json_filename : "");
596
597                 if (file_len > 0) {
598                     LOGD("Add file : %s, len : %d", file_name.c_str(), file_len);
599                     total_file_count_in_group++;
600                 } else {
601                     LOGD("Delete file : %s, len : %d", file_name.c_str(), file_len);
602                     if (create_sticker_provider_handle() == STICKER_ERROR_NONE) {
603                         delete_sticker_data(file_name.c_str());
604                         destroy_sticker_provider_handle();
605                     }
606                 }
607             }
608         }
609
610         JsonObject *j_object = json_object_new();
611         if (j_object == NULL) {
612             LOGE("Unable to json_object_new");
613             goto cleanup;
614         }
615
616         json_object_set_string_member(j_object, "msgId", STICKER_SEND_START_RSP);
617         json_object_set_int_member(j_object, "tID", t_id);
618         json_object_set_string_member(j_object, "result", "success");
619
620         if (_send_json_data(j_object) == FALSE)
621             LOGE("Failed to send message");
622
623         json_object_unref(j_object);
624     } else if (msg_id == STICKER_SEND_FACE_DATA) {
625         LOGD("msg : %s", msg_id.c_str());
626         const char *type_data = json_object_get_string_member(root_obj, "type");
627         if (type_data)
628             sticker_data.disp_type = string(type_data);
629
630         const char *category = json_object_get_string_member(root_obj, "category");
631         if (category) {
632             sticker_data.group = string(category);
633             sticker_data.keyword = string(category);
634         }
635     } else if (msg_id == STICKER_SEND_STOP_REQ) {
636         LOGD("msg : %s", msg_id.c_str());
637         const char *json_reason = json_object_get_string_member(root_obj, "reason");
638         string reason = string(json_reason ? json_reason : "");
639         int file_len = json_object_get_int_member(root_obj, "count");
640
641         JsonObject *j_object = json_object_new();
642         if (j_object == NULL) {
643             LOGE("Unable to json_object_new");
644             goto cleanup;
645         }
646
647         json_object_set_string_member(j_object, "msgId", STICKER_SEND_STOP_RSP);
648         json_object_set_int_member(j_object, "tID", t_id);
649
650         if (reason == "complete" && rec_file_cnt_in_group != file_len) {
651             json_object_set_string_member(j_object, "result", "failure");
652         }
653         else {
654             int feature_flag = 0;
655
656 #ifdef VCONFKEY_STICKER_SUPPORTED_FEATURE
657             if (vconf_get_int(VCONFKEY_STICKER_SUPPORTED_FEATURE, &feature_flag) == 0)
658             {
659                 LOGD("feature : %d, current request category : %s", feature_flag, current_request.category.c_str());
660                 if (feature_flag == VCONFKEY_STICKER_FEATURE_AREMOJI)
661                 {
662                     if (current_request.category == string("arsticker"))
663                     {
664                         set_first_sync_complete();
665                         set_sync_progressing(FALSE);
666                     }
667                 }
668                 else if (feature_flag & VCONFKEY_STICKER_FEATURE_BITMOJI)
669                 {
670                     if (current_request.category == string("bitmoji"))
671                     {
672                         set_first_sync_complete();
673                         set_sync_progressing(FALSE);
674                     }
675                 }
676             }
677             else {
678                 LOGW("Failed to read support feature");
679             }
680 #else
681             LOGW("No vconf supported feature");
682 #endif /* VCONFKEY_STICKER_SUPPORTED_FEATURE */
683
684             json_object_set_string_member(j_object, "result", "success");
685             sync_success_cnt++;
686         }
687
688         if (_send_json_data(j_object) == FALSE)
689             LOGE("Failed to send message");
690
691         json_object_unref(j_object);
692
693         send_message("sync_stop_result", reason.c_str());
694
695         if (!process_request_queue()) {
696             if (sync_success_cnt > 0 && current_request.mode == string("manual")) {
697                 if (!sync_alarm_exist())
698                     sync_alarm_register(APP_CONTROL_OPERATION_SYNC_ALARM, SYNC_ALARM_DELAY, SYNC_ALARM_INTERVAL);
699             }
700
701             sync_success_cnt = 0;
702
703             service_app_exit();
704         }
705
706         current_request.mode.clear();
707         current_request.category.clear();
708         current_request.type.clear();
709     } else
710         LOGW("unknown msg id : %s", msg_id.c_str());
711
712 cleanup:
713     if (err_msg)
714         g_error_free(err_msg);
715
716     if (parser)
717         g_object_unref(parser);
718 }
719
720 static void on_conn_req(sap_peer_agent_h peer_agent,
721                         sap_socket_h socket,
722                         sap_service_connection_result_e result,
723                         void *user_data)
724 {
725     switch (result)
726     {
727     case SAP_CONNECTION_SUCCESS:
728         LOGI("Connection success");
729         priv_data.socket = socket;
730         sap_peer_agent_accept_service_connection(peer_agent);
731         sap_peer_agent_set_service_connection_terminated_cb(peer_agent, conn_terminated, &priv_data);
732         sap_socket_set_data_received_cb(socket, on_data_received, peer_agent);
733         break;
734     case SAP_CONNECTION_ALREADY_EXIST:
735         priv_data.socket = socket;
736         LOGI("Connection Already Exist");
737         break;
738     case SAP_CONNECTION_FAILURE_DEVICE_UNREACHABLE:
739         LOGW("Connection failure device unreachable");
740         break;
741     case SAP_CONNECTION_FAILURE_INVALID_PEERAGENT:
742         LOGW("Connection failure invalid peer agent");
743         break;
744     case SAP_CONNECTION_FAILURE_NETWORK:
745         LOGW("Connection failure network");
746         break;
747     case SAP_CONNECTION_FAILURE_PEERAGENT_NO_RESPONSE:
748         LOGW("Connection failure peer agent no response");
749         break;
750     case SAP_CONNECTION_FAILURE_PEERAGENT_REJECTED:
751         LOGW("Connection failure peer agent rejected");
752         break;
753     case SAP_CONNECTION_FAILURE_UNKNOWN:
754         LOGW("Connection failure unknown");
755         break;
756     default:
757         LOGW("Connection failure. error code : %d", result);
758         break;
759     }
760 }
761
762 static void
763 _on_service_connection_created(sap_peer_agent_h peer_agent,
764                                sap_socket_h socket,
765                                sap_service_connection_result_e result,
766                                void *user_data)
767 {
768     sap_info_s *priv = (sap_info_s *)user_data;
769
770     switch (result)
771     {
772     case SAP_CONNECTION_SUCCESS:
773         sap_peer_agent_set_service_connection_terminated_cb(priv->peer_agent,
774                                                             conn_terminated,
775                                                             priv);
776
777         sap_socket_set_data_received_cb(socket, on_data_received, peer_agent);
778         priv->socket = socket;
779         LOGI("Connection Established");
780
781         process_request_queue();
782
783         break;
784
785     case SAP_CONNECTION_ALREADY_EXIST:
786         priv->socket = socket;
787         LOGI("Connection Already Exist");
788         break;
789
790     case SAP_CONNECTION_FAILURE_DEVICE_UNREACHABLE:
791         LOGW("Connection Failure device unreachable");
792         break;
793
794     case SAP_CONNECTION_FAILURE_INVALID_PEERAGENT:
795         LOGW("Connection Failure invalid peer agent");
796         break;
797
798     case SAP_CONNECTION_FAILURE_NETWORK:
799         LOGW("Connection Failure network");
800         break;
801
802     case SAP_CONNECTION_FAILURE_PEERAGENT_NO_RESPONSE:
803         LOGW("Connection Failure peer agent no response");
804         break;
805
806     case SAP_CONNECTION_FAILURE_PEERAGENT_REJECTED:
807         LOGW("Connection Failure peer agent rejected");
808         break;
809
810     case SAP_CONNECTION_FAILURE_UNKNOWN:
811         LOGW("Connection Failure peer agent unknown");
812         break;
813
814     case SAP_CONNECTION_IN_PROGRESS:
815         LOGW("Connection in progress");
816         break;
817
818     case SAP_CONNECTION_PEER_AGENT_NOT_SUPPORTED:
819         LOGW("Connection peer agent not supported");
820         break;
821     }
822 }
823
824 static gboolean
825 _create_service_connection(gpointer user_data)
826 {
827     sap_info_s *priv = (sap_info_s *)user_data;
828     int result = sap_agent_request_service_connection(priv->agent,
829                                                       priv->peer_agent,
830                                                       _on_service_connection_created,
831                                                       priv);
832
833     LOGD("request connection result : %d", result);
834
835     return FALSE;
836 }
837
838 static void
839 _on_peer_agent_updated(sap_peer_agent_h peer_agent,
840                        sap_peer_agent_status_e peer_status,
841                        sap_peer_agent_found_result_e result,
842                        void *user_data)
843 {
844     sap_info_s *priv = (sap_info_s *)user_data;
845
846     switch (result)
847     {
848     case SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED:
849         LOGW("SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED");
850         break;
851
852     case SAP_PEER_AGENT_FOUND_RESULT_FOUND:
853         if (peer_status == SAP_PEER_AGENT_STATUS_AVAILABLE)
854         {
855             LOGD("SAP_PEER_AGENT_FOUND_RESULT_FOUND");
856             priv->peer_agent = peer_agent;
857             g_idle_add(_create_service_connection, priv);
858         }
859         else
860         {
861             sap_peer_agent_destroy(peer_agent);
862         }
863         break;
864
865     case SAP_PEER_AGENT_FOUND_RESULT_SERVICE_NOT_FOUND:
866         LOGW("SAP_PEER_AGENT_FOUND_RESULT_SERVICE_NOT_FOUND");
867         break;
868
869     case SAP_PEER_AGENT_FOUND_RESULT_TIMEDOUT:
870         LOGW("SAP_PEER_AGENT_FOUND_RESULT_TIMEDOUT");
871         break;
872
873     case SAP_PEER_AGENT_FOUND_RESULT_INTERNAL_ERROR:
874         LOGW("SAP_PEER_AGENT_FOUND_RESULT_INTERNAL_ERROR");
875         break;
876
877     default:
878         break;
879     }
880 }
881
882 static gboolean
883 _find_peer_agent(gpointer user_data)
884 {
885     sap_info_s *priv = (sap_info_s *)user_data;
886     sap_agent_find_peer_agent(priv->agent, _on_peer_agent_updated, priv);
887
888     return FALSE;
889 }
890
891 static void on_agent_initialized(sap_agent_h agent,
892                                  sap_agent_initialized_result_e result,
893                                  void *user_data)
894 {
895     switch (result) {
896         case SAP_AGENT_INITIALIZED_RESULT_SUCCESS:
897             LOGD("agent is initialized");
898
899             priv_data.agent = agent;
900
901             sap_file_transfer_set_incoming_file_cb(agent, _on_receive_file_cb, NULL);
902             sap_agent_set_service_connection_requested_cb(agent, on_conn_req, NULL);
903
904             break;
905         case SAP_AGENT_INITIALIZED_RESULT_DUPLICATED:
906             LOGE("duplicate registration");
907             break;
908         case SAP_AGENT_INITIALIZED_RESULT_INVALID_ARGUMENTS:
909             LOGE("invalid arguments");
910             break;
911         case SAP_AGENT_INITIALIZED_RESULT_INTERNAL_ERROR:
912             LOGE("internal sap error");
913             break;
914         default:
915             LOGE("unknown status (%d)", result);
916             break;
917     }
918 }
919
920 static void on_agent_deinitialized(sap_agent_h agent,
921                                    sap_agent_deinitialized_result_e result,
922                                    void *user_data)
923 {
924     LOGD("result of deinitialize : %d", result);
925 }
926
927 static void _on_device_status_changed(sap_device_status_e status,
928                                       sap_transport_type_e transport_type,
929                                       void *user_data)
930 {
931     LOGD("%s, status :%d", __func__, status);
932
933     switch (transport_type) {
934         case SAP_TRANSPORT_TYPE_BT:
935             LOGD("transport_type (%d): bt", transport_type);
936             break;
937         case SAP_TRANSPORT_TYPE_BLE:
938             LOGD("transport_type (%d): ble", transport_type);
939             break;
940         case SAP_TRANSPORT_TYPE_TCP:
941             LOGD("transport_type (%d): tcp/ip", transport_type);
942             break;
943         case SAP_TRANSPORT_TYPE_USB:
944             LOGD("transport_type (%d): usb", transport_type);
945             break;
946         case SAP_TRANSPORT_TYPE_MOBILE:
947             LOGD("transport_type (%d): mobile", transport_type);
948             break;
949         default:
950             LOGE("unknown transport_type (%d)", transport_type);
951             break;
952     }
953
954     switch (status) {
955         case SAP_DEVICE_STATUS_DETACHED:
956             LOGD("device is not connected.");
957             break;
958         case SAP_DEVICE_STATUS_ATTACHED:
959             LOGD("Attached calling find peer now");
960             g_idle_add(_find_peer_agent, &priv_data);
961             break;
962         default:
963             LOGE("unknown status (%d)", status);
964             break;
965     }
966 }
967
968 gboolean agent_initialize()
969 {
970     int result = 0;
971
972     do {
973         result = sap_agent_initialize(priv_data.agent, ACCESSORY_SERVICE_PROFILE_ID, SAP_AGENT_ROLE_CONSUMER,
974                 on_agent_initialized, NULL);
975
976         LOGD("SAP >>> getRegisteredServiceAgent() >>> %d", result);
977     } while (result != SAP_RESULT_SUCCESS);
978
979     return TRUE;
980 }
981
982 gboolean initialize_sap(void)
983 {
984     sap_agent_h agent = NULL;
985
986     sap_agent_create(&agent);
987
988     priv_data.agent = agent;
989
990     agent_initialize();
991
992     sap_set_device_status_changed_cb(_on_device_status_changed, NULL);
993
994     return TRUE;
995 }
996
997 void deinitialize_sap(void)
998 {
999     if (priv_data.agent) {
1000         int ret = sap_agent_deinitialize(priv_data.agent, on_agent_deinitialized, NULL);
1001         switch (ret) {
1002             case SAP_RESULT_FAILURE:
1003                 LOGW("Failed to deinitialize");
1004                 break;
1005             case SAP_RESULT_SUCCESS:
1006                 LOGD("Succeed to deinitialize");
1007                 break;
1008             case SAP_RESULT_PERMISSION_DENIED:
1009                 LOGW("permission denied: deinitialize ");
1010                 break;
1011             default:
1012                 LOGD("deinitialize : %d", ret);
1013                 break;
1014         }
1015
1016         sap_agent_destroy(priv_data.agent);
1017         priv_data.agent = NULL;
1018     }
1019 }