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