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