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