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