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