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