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