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