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