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