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