Reduce duplicated code
[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             if (!request_sticker_data(mode, "arsticker", type))
419                 LOGW("Failed to request ar_sticker sync");
420
421         if (feature_flag & VCONFKEY_STICKER_FEATURE_BITMOJI)
422             if (!request_sticker_data(mode, "bitmoji", type))
423                 LOGW("Failed to request bitmoji sync");
424     }
425     else
426         LOGW("Failed to get value of VCONFKEY_STICKER_SUPPORTED_FEATURE");
427 #else
428     request_sticker_data(mode, "arsticker", type);
429     request_sticker_data(mode, "bitmoji", type);
430 #endif
431 }
432
433 void request_sticker_feature()
434 {
435     JsonObject *j_object = NULL;
436
437     if (!priv_data.socket) {
438         job_progress = TRUE;
439         StickerRequest pending_request;
440         pending_request.req_type = REQUEST_TYPE_FEATURE_REQ;
441         ReqQueue.push(pending_request);
442         LOGI("Push sync feature request");
443         return;
444     }
445
446     j_object = json_object_new();
447     if (j_object == NULL) {
448         LOGE("json object create error");
449         return;
450     }
451
452     json_object_set_string_member(j_object, "msgId", STICKER_SYNC_FEATURE_REQ);
453     json_object_set_int_member(j_object, "tID", ++t_id);
454
455     if (_send_json_data(j_object) == FALSE) {
456         LOGE("Failed to send STICKER_SYNC_FEATURE_REQ");
457     }
458     else {
459         job_progress = TRUE;
460     }
461
462     json_object_unref(j_object);
463
464     if (_create_thumbnail_directory() != 0)
465         LOGE("Failed to create thumbnail directory");
466 }
467
468 void send_disconnect_message()
469 {
470     JsonObject *j_object = NULL;
471     j_object = json_object_new();
472     if (j_object == NULL) {
473         LOGE("json object create error");
474         return;
475     }
476
477     json_object_set_string_member(j_object, "msgId", STICKER_SEND_DISCONNECT_REQ);
478     json_object_set_int_member(j_object, "tID", t_id);
479
480     if (_send_json_data(j_object) == FALSE) {
481         LOGE("Failed to send STICKER_SEND_DISCONNECT_REQ");
482     }
483
484     json_object_unref(j_object);
485 }
486
487 void reject_file()
488 {
489     int ret = sap_file_transfer_reject(priv_data.file_socket);
490     LOGI("ret : %d", ret);
491
492     file_on_progress = FALSE;
493 }
494
495 static void _on_transfer_file_cb(sap_peer_agent_h peer_agent_h,
496                                  sap_file_transaction_h socket,
497                                  const char *file_path,
498                                  void *user_data)
499 {
500     file_on_progress = TRUE;
501     priv_data.file_socket = socket;
502     LOGI("# incoming file request.");
503     __set_file_transfer_cb(priv_data.file_socket);
504
505     incoming_file_name = file_path;
506     std::size_t found = incoming_file_name.find_last_of("/");
507     incoming_file_name = incoming_file_name.substr(found+1);
508
509     LOGI("# file path : %s, incoming file name : %s", file_path, incoming_file_name.c_str());
510
511     accept_file();
512 }
513
514 void conn_terminated(sap_peer_agent_h peer_agent,
515                      sap_socket_h socket,
516                      sap_service_connection_terminated_reason_e result,
517                      void *user_data)
518 {
519     sap_info_s *priv = NULL;
520     priv = (sap_info_s *)user_data;
521
522     switch (result)
523     {
524     case SAP_CONNECTION_TERMINATED_REASON_PEER_DISCONNECTED:
525         LOGW("Peer Disconnected");
526         break;
527     case SAP_CONNECTION_TERMINATED_REASON_DEVICE_DETACHED:
528         LOGW("Disconnected Device Detached");
529         break;
530     case SAP_CONNECTION_TERMINATED_REASON_UNKNOWN:
531         LOGW("Disconnected Unknown Reason");
532         break;
533     default:
534         LOGW("connection terminated. reason : %d", result);
535         break;
536     }
537
538     sap_socket_destroy(priv->socket);
539     priv->socket = NULL;
540
541     set_sync_progressing(FALSE);
542     service_app_exit();
543 }
544
545 static bool process_request_queue()
546 {
547     if (ReqQueue.empty())
548         return false;
549
550     StickerRequest request = ReqQueue.front();
551
552     if (request.req_type == REQUEST_TYPE_FEATURE_REQ) {
553         LOGD("[Request feature exchange]");
554         request_sticker_feature();
555         ReqQueue.pop();
556     }
557     else if (request.req_type == REQUEST_TYPE_SYNC) {
558         LOGD("[Request to sync sticker] mode: %s, category: %s, type : %s", request.mode.c_str(),
559                 request.category.c_str(),
560                 request.type.c_str());
561
562         if (request_sticker_data(request.mode.c_str(), request.category.c_str(), request.type.c_str()))
563             ReqQueue.pop();
564     }
565
566     return true;
567 }
568
569 static void quit()
570 {
571     job_progress = FALSE;
572     send_disconnect_message();
573     service_app_exit();
574 }
575
576 void
577 on_data_received(sap_socket_h socket, unsigned short int channel_id, unsigned int payload_length, void *buffer,
578                  void *user_data) /* message exchange on_receive callback (sap_agent_data_received_cb) */
579 {
580     unsigned int buf_len = strlen((char *)buffer);
581     LOGI("received data: %s, len: %d, buffer len : %d", (char *)buffer, payload_length, buf_len);
582
583     JsonParser *parser = json_parser_new();
584     GError *err_msg = NULL;
585     JsonNode *root = NULL;
586     JsonObject *root_obj = NULL;
587     string msg_id;
588     const char *json_msgid = NULL;
589
590     json_parser_load_from_data(parser, (char *)buffer, payload_length, &err_msg);
591     if (err_msg) {
592         LOGE("failed to load json file. error message: %s", err_msg->message);
593         goto cleanup;
594     }
595
596     root = json_parser_get_root(parser);
597     if (root == NULL) {
598         LOGE("failed to get root");
599         goto cleanup;
600     }
601
602     root_obj = json_node_get_object(root);
603     if (root_obj == NULL) {
604         LOGE("failed to get object");
605         goto cleanup;
606     }
607
608     json_msgid = json_object_get_string_member(root_obj, "msgId");
609     msg_id = string(json_msgid ? json_msgid : "");
610     if (msg_id == STICKER_REQUEST_SYNC_REQ) {
611         request_all_sticker_data("auto", "input");
612     } else if (msg_id == STICKER_SYNC_FEATURE_RSP) {
613         LOGD("msg : %s", msg_id.c_str());
614 #ifdef VCONFKEY_STICKER_SUPPORTED_FEATURE
615         const char *json_aremoji = json_object_get_string_member(root_obj, "arEmoji");
616         const char *json_bitmoji = json_object_get_string_member(root_obj, "bitmoji");
617         string support_aremoji = string(json_aremoji ? json_aremoji : "");
618         string support_bitmoji = string(json_bitmoji ? json_bitmoji : "");
619         int supported_feature = VCONFKEY_STICKER_FEATURE_NONE;
620
621         if (support_aremoji == "support")
622             supported_feature |= VCONFKEY_STICKER_FEATURE_AREMOJI;
623
624         if (support_bitmoji == "support")
625             supported_feature |= VCONFKEY_STICKER_FEATURE_BITMOJI;
626
627         if (vconf_set_int(VCONFKEY_STICKER_SUPPORTED_FEATURE, supported_feature) == 0)
628             LOGD("Succeed to set supported feature");
629         else
630             LOGW("Fail to set supported feature");
631 #else
632         LOGW("No vconf supported feature");
633 #endif
634
635         if (!process_request_queue()) {
636             quit();
637         }
638     } else if (msg_id == STICKER_SYNC_START_RSP) {
639         LOGD("msg : %s", msg_id.c_str());
640         const char *json_result = json_object_get_string_member(root_obj, "result");
641         string result = string(json_result ? json_result : "");
642         int result_code = json_object_get_int_member(root_obj, "resultCode");
643         LOGD("result : %s, resultCode : %d", result.c_str(), result_code);
644
645         string response_to_app;
646         switch (result_code) {
647         case SYNC_START_RSP_SUCCESS:
648             response_to_app = "success";
649             break;
650         case SYNC_START_RSP_NO_STICKER:
651             response_to_app = "no_sticker";
652             break;
653         default:
654             response_to_app = "unknown_error";
655             break;
656         }
657
658         send_message("sync_start_response", response_to_app.c_str());
659
660         if (result_code != SYNC_START_RSP_SUCCESS) {
661             set_sync_progressing(FALSE);
662             if (!process_request_queue()) {
663                 if (result_code == SYNC_START_RSP_NO_STICKER)
664                     save_last_sync_time();
665
666                 quit();
667             }
668         }
669     } else if (msg_id == STICKER_SEND_START_REQ) {
670         LOGD("msg : %s", msg_id.c_str());
671         total_file_count_in_group = 0;
672         rec_file_cnt_in_group = 0;
673         t_id = json_object_get_int_member(root_obj, "tID");
674         JsonArray *file_list = json_object_get_array_member(root_obj, "list");
675         if (file_list) {
676             int arr_len = json_array_get_length(file_list);
677             for (int i = 0; i < arr_len; i++) {
678                 JsonObject *file_obj = json_array_get_object_element(file_list, i);
679                 int file_len = json_object_get_int_member(file_obj, "size");
680                 const char *json_filename = json_object_get_string_member(file_obj, "fileName");
681                 string file_name = string(json_filename ? json_filename : "");
682
683                 if (file_len > 0) {
684                     LOGD("Add file : %s, len : %d", file_name.c_str(), file_len);
685                     total_file_count_in_group++;
686                 } else {
687                     LOGD("Delete file : %s, len : %d", file_name.c_str(), file_len);
688                     if (create_sticker_provider_handle() == STICKER_ERROR_NONE) {
689                         delete_sticker_data(file_name.c_str());
690                         destroy_sticker_provider_handle();
691                     }
692                 }
693             }
694         }
695
696         JsonObject *j_object = json_object_new();
697         if (j_object == NULL) {
698             LOGE("Unable to json_object_new");
699             goto cleanup;
700         }
701
702         json_object_set_string_member(j_object, "msgId", STICKER_SEND_START_RSP);
703         json_object_set_int_member(j_object, "tID", t_id);
704         json_object_set_string_member(j_object, "result", "success");
705
706         if (_send_json_data(j_object) == FALSE)
707             LOGE("Failed to send message");
708
709         json_object_unref(j_object);
710     } else if (msg_id == STICKER_SEND_FACE_DATA) {
711         LOGD("msg : %s", msg_id.c_str());
712         const char *type_data = json_object_get_string_member(root_obj, "type");
713         if (type_data)
714             sticker_data.disp_type = string(type_data);
715
716         const char *category = json_object_get_string_member(root_obj, "category");
717         if (category) {
718             sticker_data.group = string(category);
719             sticker_data.keyword = string(category);
720         }
721     } else if (msg_id == STICKER_SEND_STOP_REQ) {
722         LOGD("msg : %s", msg_id.c_str());
723         const char *json_reason = json_object_get_string_member(root_obj, "reason");
724         string reason = string(json_reason ? json_reason : "");
725         int file_len = json_object_get_int_member(root_obj, "count");
726
727         JsonObject *j_object = json_object_new();
728         if (j_object == NULL) {
729             LOGE("Unable to json_object_new");
730             goto cleanup;
731         }
732
733         json_object_set_string_member(j_object, "msgId", STICKER_SEND_STOP_RSP);
734         json_object_set_int_member(j_object, "tID", t_id);
735
736         if (reason == "complete" && rec_file_cnt_in_group != file_len) {
737             json_object_set_string_member(j_object, "result", "failure");
738         }
739         else {
740             int feature_flag = 0;
741
742 #ifdef VCONFKEY_STICKER_SUPPORTED_FEATURE
743             if (vconf_get_int(VCONFKEY_STICKER_SUPPORTED_FEATURE, &feature_flag) == 0)
744             {
745                 LOGD("feature : %d, current request category : %s", feature_flag, current_request.category.c_str());
746                 if (feature_flag == VCONFKEY_STICKER_FEATURE_AREMOJI)
747                 {
748                     if (current_request.category == string("arsticker"))
749                     {
750                         set_sync_complete();
751                         set_sync_progressing(FALSE);
752                     }
753                 }
754                 else if (feature_flag & VCONFKEY_STICKER_FEATURE_BITMOJI)
755                 {
756                     if (current_request.category == string("bitmoji"))
757                     {
758                         set_sync_complete();
759                         set_sync_progressing(FALSE);
760                     }
761                 }
762             }
763             else {
764                 LOGW("Failed to read support feature");
765             }
766 #else
767             LOGW("No vconf supported feature");
768 #endif /* VCONFKEY_STICKER_SUPPORTED_FEATURE */
769
770             json_object_set_string_member(j_object, "result", "success");
771             sync_success_cnt++;
772         }
773
774         if (_send_json_data(j_object) == FALSE)
775             LOGE("Failed to send message");
776
777         json_object_unref(j_object);
778
779         send_message("sync_stop_result", reason.c_str());
780
781         current_request.mode.clear();
782         current_request.category.clear();
783         current_request.type.clear();
784
785         if (!process_request_queue()) {
786             sync_success_cnt = 0;
787
788             quit();
789         }
790     } else
791         LOGW("unknown msg id : %s", msg_id.c_str());
792
793 cleanup:
794     if (err_msg)
795         g_error_free(err_msg);
796
797     if (parser)
798         g_object_unref(parser);
799 }
800
801 static void on_conn_req(sap_peer_agent_h peer_agent,
802                         sap_socket_h socket,
803                         sap_service_connection_result_e result,
804                         void *user_data)
805 {
806     switch (result)
807     {
808     case SAP_CONNECTION_SUCCESS:
809         LOGI("Connection success");
810         priv_data.socket = socket;
811         sap_peer_agent_accept_service_connection(peer_agent);
812         sap_peer_agent_set_service_connection_terminated_cb(peer_agent, conn_terminated, &priv_data);
813         sap_socket_set_data_received_cb(socket, on_data_received, peer_agent);
814         break;
815     case SAP_CONNECTION_ALREADY_EXIST:
816         priv_data.socket = socket;
817         LOGI("Connection Already Exist");
818         break;
819     case SAP_CONNECTION_FAILURE_DEVICE_UNREACHABLE:
820         LOGW("Connection failure device unreachable");
821         break;
822     case SAP_CONNECTION_FAILURE_INVALID_PEERAGENT:
823         LOGW("Connection failure invalid peer agent");
824         break;
825     case SAP_CONNECTION_FAILURE_NETWORK:
826         LOGW("Connection failure network");
827         break;
828     case SAP_CONNECTION_FAILURE_PEERAGENT_NO_RESPONSE:
829         LOGW("Connection failure peer agent no response");
830         break;
831     case SAP_CONNECTION_FAILURE_PEERAGENT_REJECTED:
832         LOGW("Connection failure peer agent rejected");
833         break;
834     case SAP_CONNECTION_FAILURE_UNKNOWN:
835         LOGW("Connection failure unknown");
836         break;
837     default:
838         LOGW("Connection failure. error code : %d", result);
839         break;
840     }
841 }
842
843 static void
844 _on_service_connection_created(sap_peer_agent_h peer_agent,
845                                sap_socket_h socket,
846                                sap_service_connection_result_e result,
847                                void *user_data)
848 {
849     sap_info_s *priv = (sap_info_s *)user_data;
850
851     switch (result)
852     {
853     case SAP_CONNECTION_SUCCESS:
854         sap_peer_agent_set_service_connection_terminated_cb(priv->peer_agent,
855                                                             conn_terminated,
856                                                             priv);
857
858         sap_socket_set_data_received_cb(socket, on_data_received, peer_agent);
859         priv->socket = socket;
860         LOGI("Connection Established");
861
862         process_request_queue();
863
864         break;
865
866     case SAP_CONNECTION_ALREADY_EXIST:
867         priv->socket = socket;
868         LOGI("Connection Already Exist");
869         break;
870
871     case SAP_CONNECTION_FAILURE_DEVICE_UNREACHABLE:
872         LOGW("Connection Failure device unreachable");
873         break;
874
875     case SAP_CONNECTION_FAILURE_INVALID_PEERAGENT:
876         LOGW("Connection Failure invalid peer agent");
877         break;
878
879     case SAP_CONNECTION_FAILURE_NETWORK:
880         LOGW("Connection Failure network");
881         break;
882
883     case SAP_CONNECTION_FAILURE_PEERAGENT_NO_RESPONSE:
884         LOGW("Connection Failure peer agent no response");
885         break;
886
887     case SAP_CONNECTION_FAILURE_PEERAGENT_REJECTED:
888         LOGW("Connection Failure peer agent rejected");
889         break;
890
891     case SAP_CONNECTION_FAILURE_UNKNOWN:
892         LOGW("Connection Failure peer agent unknown");
893         break;
894
895     case SAP_CONNECTION_IN_PROGRESS:
896         LOGW("Connection in progress");
897         break;
898
899     case SAP_CONNECTION_PEER_AGENT_NOT_SUPPORTED:
900         LOGW("Connection peer agent not supported");
901         break;
902     }
903 }
904
905 static gboolean
906 _create_service_connection(gpointer user_data)
907 {
908     sap_info_s *priv = (sap_info_s *)user_data;
909     int result = sap_agent_request_service_connection(priv->agent,
910                                                       priv->peer_agent,
911                                                       _on_service_connection_created,
912                                                       priv);
913
914     LOGD("request connection result : %d", result);
915
916     return FALSE;
917 }
918
919 static void
920 _on_peer_agent_updated(sap_peer_agent_h peer_agent,
921                        sap_peer_agent_status_e peer_status,
922                        sap_peer_agent_found_result_e result,
923                        void *user_data)
924 {
925     sap_info_s *priv = (sap_info_s *)user_data;
926
927     switch (result)
928     {
929     case SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED:
930         LOGW("SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED");
931         break;
932
933     case SAP_PEER_AGENT_FOUND_RESULT_FOUND:
934         if (peer_status == SAP_PEER_AGENT_STATUS_AVAILABLE)
935         {
936             LOGD("SAP_PEER_AGENT_FOUND_RESULT_FOUND");
937             priv->peer_agent = peer_agent;
938             g_idle_add(_create_service_connection, priv);
939         }
940         else
941         {
942             sap_peer_agent_destroy(peer_agent);
943         }
944         break;
945
946     case SAP_PEER_AGENT_FOUND_RESULT_SERVICE_NOT_FOUND:
947         LOGW("SAP_PEER_AGENT_FOUND_RESULT_SERVICE_NOT_FOUND");
948         break;
949
950     case SAP_PEER_AGENT_FOUND_RESULT_TIMEDOUT:
951         LOGW("SAP_PEER_AGENT_FOUND_RESULT_TIMEDOUT");
952         break;
953
954     case SAP_PEER_AGENT_FOUND_RESULT_INTERNAL_ERROR:
955         LOGW("SAP_PEER_AGENT_FOUND_RESULT_INTERNAL_ERROR");
956         break;
957
958     default:
959         break;
960     }
961 }
962
963 static gboolean
964 _find_peer_agent(gpointer user_data)
965 {
966     sap_info_s *priv = (sap_info_s *)user_data;
967     sap_agent_find_peer_agent(priv->agent, _on_peer_agent_updated, priv);
968
969     return FALSE;
970 }
971
972 static void on_agent_initialized(sap_agent_h agent,
973                                  sap_agent_initialized_result_e result,
974                                  void *user_data)
975 {
976     switch (result) {
977         case SAP_AGENT_INITIALIZED_RESULT_SUCCESS:
978             LOGD("agent is initialized");
979
980             priv_data.agent = agent;
981
982             sap_file_transfer_set_incoming_file_cb(agent, _on_transfer_file_cb, NULL);
983             sap_agent_set_service_connection_requested_cb(agent, on_conn_req, NULL);
984
985             break;
986         case SAP_AGENT_INITIALIZED_RESULT_DUPLICATED:
987             LOGE("duplicate registration");
988             break;
989         case SAP_AGENT_INITIALIZED_RESULT_INVALID_ARGUMENTS:
990             LOGE("invalid arguments");
991             break;
992         case SAP_AGENT_INITIALIZED_RESULT_INTERNAL_ERROR:
993             LOGE("internal sap error");
994             break;
995         default:
996             LOGE("unknown status (%d)", result);
997             break;
998     }
999 }
1000
1001 static void on_agent_deinitialized(sap_agent_h agent,
1002                                    sap_agent_deinitialized_result_e result,
1003                                    void *user_data)
1004 {
1005     LOGD("result of deinitialize : %d", result);
1006 }
1007
1008 static void _on_device_status_changed(sap_device_status_e status,
1009                                       sap_transport_type_e transport_type,
1010                                       void *user_data)
1011 {
1012     LOGD("%s, status :%d", __func__, status);
1013
1014     switch (transport_type) {
1015         case SAP_TRANSPORT_TYPE_BT:
1016             LOGD("transport_type (%d): bt", transport_type);
1017             break;
1018         case SAP_TRANSPORT_TYPE_BLE:
1019             LOGD("transport_type (%d): ble", transport_type);
1020             break;
1021         case SAP_TRANSPORT_TYPE_TCP:
1022             LOGD("transport_type (%d): tcp/ip", transport_type);
1023             break;
1024         case SAP_TRANSPORT_TYPE_USB:
1025             LOGD("transport_type (%d): usb", transport_type);
1026             break;
1027         case SAP_TRANSPORT_TYPE_MOBILE:
1028             LOGD("transport_type (%d): mobile", transport_type);
1029             break;
1030         default:
1031             LOGE("unknown transport_type (%d)", transport_type);
1032             break;
1033     }
1034
1035     switch (status) {
1036         case SAP_DEVICE_STATUS_DETACHED:
1037             LOGD("device is not connected.");
1038             break;
1039         case SAP_DEVICE_STATUS_ATTACHED:
1040             LOGD("Attached calling find peer now");
1041             g_idle_add(_find_peer_agent, &priv_data);
1042             break;
1043         default:
1044             LOGE("unknown status (%d)", status);
1045             break;
1046     }
1047 }
1048
1049 gboolean agent_initialize()
1050 {
1051     int result = 0;
1052
1053     do {
1054         result = sap_agent_initialize(priv_data.agent, ACCESSORY_SERVICE_PROFILE_ID, SAP_AGENT_ROLE_CONSUMER,
1055                 on_agent_initialized, NULL);
1056
1057         LOGD("SAP >>> getRegisteredServiceAgent() >>> %d", result);
1058     } while (result != SAP_RESULT_SUCCESS);
1059
1060     return TRUE;
1061 }
1062
1063 gboolean initialize_sap(void)
1064 {
1065     sap_agent_h agent = NULL;
1066
1067     if (priv_data.agent) {
1068         LOGW("duplicate initialize");
1069         return FALSE;
1070     }
1071
1072     sap_agent_create(&agent);
1073
1074     priv_data.agent = agent;
1075
1076     agent_initialize();
1077
1078     sap_set_device_status_changed_cb(_on_device_status_changed, NULL);
1079
1080     return TRUE;
1081 }
1082
1083 void deinitialize_sap(void)
1084 {
1085     LOGD("deinitialize");
1086     if (priv_data.agent) {
1087         int ret = sap_agent_deinitialize(priv_data.agent, on_agent_deinitialized, NULL);
1088         switch (ret) {
1089             case SAP_RESULT_FAILURE:
1090                 LOGW("Failed to deinitialize");
1091                 break;
1092             case SAP_RESULT_SUCCESS:
1093                 LOGD("Succeed to deinitialize");
1094                 break;
1095             case SAP_RESULT_PERMISSION_DENIED:
1096                 LOGW("permission denied: deinitialize ");
1097                 break;
1098             default:
1099                 LOGD("deinitialize : %d", ret);
1100                 break;
1101         }
1102
1103         sap_agent_destroy(priv_data.agent);
1104         priv_data.agent = NULL;
1105     }
1106 }
1107
1108 gboolean is_init_sap()
1109 {
1110     return priv_data.agent ? TRUE : FALSE;
1111 }