2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <service_app.h>
21 #include <app_common.h>
23 #include <sap_file_transfer.h>
24 #include <sticker_provider.h>
28 #include <linux/limits.h>
29 #include <sys/types.h>
32 #include <json-glib/json-glib.h>
36 #include "sticker_info.h"
39 #define ACCESSORY_SERVICE_PROFILE_ID "/sample/filetransfersender"
40 #define ACCESSORY_SERVICE_CHANNEL_ID 107
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"
55 sap_peer_agent_h peer_agent;
56 sap_file_transaction_h file_socket;
65 static void _reset_sticker_data();
76 _reset_sticker_data();
80 static struct sap_info_s priv_data = { 0 };
81 static struct sticker_info sticker_data;
82 static struct sync_request pending_sync_request;
84 gboolean file_on_progress = 0;
85 static string incoming_file_name;
87 static int rec_file_cnt = 0;
88 static int total_file_count = 0;
90 static gboolean _send_json_data(JsonObject *obj)
92 JsonGenerator *j_generator = NULL;
93 JsonNode *j_node = NULL;
98 j_generator = json_generator_new();
99 if (j_generator == NULL) {
100 LOGE("Unable to json_generator_new");
104 j_node = json_node_new(JSON_NODE_OBJECT);
105 if (j_node == NULL) {
106 LOGE("Unable to json_node_new");
110 json_node_set_object(j_node, obj);
111 json_generator_set_root(j_generator, j_node);
113 data = json_generator_to_data(j_generator, &size);
115 LOGE("Unable to json_generator_to_data");
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);
129 json_node_free(j_node);
132 g_object_unref(j_generator);
134 return result ? FALSE : TRUE;
137 static void notify_sync_progress(unsigned int file_progress)
139 if (total_file_count == 0)
142 double total_progress = (((double)rec_file_cnt / (double)total_file_count) + (1.0/(double)total_file_count*file_progress/100))*100;
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);
150 static void _on_send_completed(sap_file_transaction_h file_transaction,
151 sap_ft_transfer_e result,
152 const char *file_path,
155 if (priv_data.file_socket) {
156 sap_file_transfer_destroy(file_transaction);
157 priv_data.file_socket = NULL;
160 if (result == SAP_FT_TRANSFER_SUCCESS) {
161 LOGI("Transfer Completed");
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));
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();
172 if (unlink(sticker_data.file_path.c_str()) == -1)
173 LOGE("Failed to remove sticker file");
180 case (SAP_FT_TRANSFER_FAIL_CHANNEL_IO): {
181 LOGW("Channel IO Error.");
185 case (SAP_FT_TRANSFER_FAIL_FILE_IO): {
186 LOGW("File IO Error.");
190 case (SAP_FT_TRANSFER_FAIL_CMD_DROPPED):
192 LOGW("Transfer dropped.");
196 case (SAP_FT_TRANSFER_FAIL_PEER_UNRESPONSIVE):
198 LOGW("Peer Un Responsive.");
202 case (SAP_FT_TRANSFER_FAIL_PEER_CONN_LOST):
204 LOGW("Connection Lost.");
208 case (SAP_FT_TRANSFER_FAIL_PEER_CANCELLED):
210 LOGW("Peer Cancelled.");
214 case (SAP_FT_TRANSFER_FAIL_SPACE_NOT_AVAILABLE):
221 LOGW("Unknown Error");
226 file_on_progress = 0;
229 static void _on_sending_file_in_progress(sap_file_transaction_h file_transaction,
230 unsigned short int percentage_progress,
233 LOGI("# progress %d", percentage_progress);
234 notify_sync_progress(percentage_progress);
237 static void __set_file_transfer_cb(sap_file_transaction_h file_socket)
239 LOGI("# set callbacks");
240 sap_file_transfer_set_progress_cb(file_socket, _on_sending_file_in_progress, NULL);
242 sap_file_transfer_set_done_cb(file_socket, _on_send_completed, NULL);
248 char file_path[PATH_MAX];
249 char *data_path = NULL;
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);
258 ret = sap_file_transfer_receive(priv_data.file_socket, file_path);
260 case SAP_RESULT_PERMISSION_DENIED:
261 LOGW("permission denied");
263 case SAP_RESULT_FAILURE:
266 case SAP_RESULT_SUCCESS:
271 file_on_progress = 1;
274 void sap_file_transfer_get_receive_filepath(char **filepath)
276 *filepath = strdup(sticker_data.file_path.c_str());
279 void request_sticker_data(const char *mode, const char *category, const char *type)
281 JsonObject *j_object = json_object_new();
282 if (j_object == NULL) {
283 LOGE("json object create error");
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);
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");
298 LOGI("Push sync request");
301 json_object_unref(j_object);
306 int ret = sap_file_transfer_reject(priv_data.file_socket);
307 LOGI("ret : %d", ret);
309 file_on_progress = 0;
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,
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);
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);
326 LOGI("# file path : %s, incoming file name : %s", file_path, incoming_file_name.c_str());
331 void conn_terminated(sap_peer_agent_h peer_agent,
333 sap_service_connection_terminated_reason_e result,
336 sap_info_s *priv = NULL;
337 priv = (sap_info_s *)user_data;
341 case SAP_CONNECTION_TERMINATED_REASON_PEER_DISCONNECTED:
342 LOGW("Peer Disconnected");
344 case SAP_CONNECTION_TERMINATED_REASON_DEVICE_DETACHED:
345 LOGW("Disconnected Device Detached");
347 case SAP_CONNECTION_TERMINATED_REASON_UNKNOWN:
348 LOGW("Disconnected Unknown Reason");
351 LOGW("connection terminated. reason : %d", result);
355 sap_socket_destroy(priv->socket);
361 static void _reset_sticker_data()
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();
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) */
374 LOGI("received data: %s, len:%d", (char *)buffer, payload_length);
376 JsonParser *parser = json_parser_new();
377 GError *err_msg = NULL;
378 JsonNode *root = NULL;
379 JsonObject *root_obj = NULL;
381 const char *json_msgid = NULL;
383 json_parser_load_from_data(parser, (char *)buffer, -1, &err_msg);
385 LOGE("failed to load json file. error message: %s", err_msg->message);
389 root = json_parser_get_root(parser);
391 LOGE("failed to get root");
395 root_obj = json_node_get_object(root);
396 if (root_obj == NULL) {
397 LOGE("failed to get object");
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;
413 t_id = json_object_get_int_member(root_obj, "tID");
414 JsonArray *file_list = json_object_get_array_member(root_obj, "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");
424 string file_name = string(json_filename ? json_filename : "");
427 LOGD("fileName : %s, len : %d", file_name.c_str(), file_len);
431 LOGD("fileName : %s, len : %d", file_name.c_str(), file_len);
436 JsonObject *j_object = json_object_new();
437 if (j_object == NULL) {
438 LOGE("Unable to json_object_new");
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");
446 if (_send_json_data(j_object) == FALSE)
447 LOGE("Failed to send message");
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();
454 const char *type_data = json_object_get_string_member(root_obj, "type");
456 sticker_data.disp_type = string(type_data);
458 const char *category = json_object_get_string_member(root_obj, "category");
460 sticker_data.group = string(category);
461 sticker_data.keyword = string(category);
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");
469 JsonObject *j_object = json_object_new();
470 if (j_object == NULL) {
471 LOGE("Unable to json_object_new");
475 json_object_set_string_member(j_object, "msgId", STICKER_SEND_STOP_RSP);
476 json_object_set_int_member(j_object, "tID", t_id);
478 if (reason == "complete" && rec_file_cnt != file_len)
479 json_object_set_string_member(j_object, "result", "failure");
481 json_object_set_string_member(j_object, "result", "success");
483 if (_send_json_data(j_object) == FALSE)
484 LOGE("Failed to send message");
486 json_object_unref(j_object);
488 LOGW("unknown msg id : %s", msg_id.c_str());
492 g_error_free(err_msg);
495 g_object_unref(parser);
498 static void on_conn_req(sap_peer_agent_h peer_agent,
500 sap_service_connection_result_e result,
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);
512 case SAP_CONNECTION_ALREADY_EXIST:
513 priv_data.socket = socket;
514 LOGI("Connection Already Exist");
516 case SAP_CONNECTION_FAILURE_DEVICE_UNREACHABLE:
517 LOGW("Connection failure device unreachable");
519 case SAP_CONNECTION_FAILURE_INVALID_PEERAGENT:
520 LOGW("Connection failure invalid peer agent");
522 case SAP_CONNECTION_FAILURE_NETWORK:
523 LOGW("Connection failure network");
525 case SAP_CONNECTION_FAILURE_PEERAGENT_NO_RESPONSE:
526 LOGW("Connection failure peer agent no response");
528 case SAP_CONNECTION_FAILURE_PEERAGENT_REJECTED:
529 LOGW("Connection failure peer agent rejected");
531 case SAP_CONNECTION_FAILURE_UNKNOWN:
532 LOGW("Connection failure unknown");
535 LOGW("Connection failure. error code : %d", result);
541 _on_service_connection_created(sap_peer_agent_h peer_agent,
543 sap_service_connection_result_e result,
546 sap_info_s *priv = (sap_info_s *)user_data;
550 case SAP_CONNECTION_SUCCESS:
551 sap_peer_agent_set_service_connection_terminated_cb(priv->peer_agent,
555 sap_socket_set_data_received_cb(socket, on_data_received, peer_agent);
556 priv->socket = socket;
557 LOGI("Connection Established");
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());
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();
572 case SAP_CONNECTION_ALREADY_EXIST:
573 priv->socket = socket;
574 LOGI("Connection Already Exist");
577 case SAP_CONNECTION_FAILURE_DEVICE_UNREACHABLE:
578 LOGW("Connection Failure device unreachable");
581 case SAP_CONNECTION_FAILURE_INVALID_PEERAGENT:
582 LOGW("Connection Failure invalid peer agent");
585 case SAP_CONNECTION_FAILURE_NETWORK:
586 LOGW("Connection Failure network");
589 case SAP_CONNECTION_FAILURE_PEERAGENT_NO_RESPONSE:
590 LOGW("Connection Failure peer agent no response");
593 case SAP_CONNECTION_FAILURE_PEERAGENT_REJECTED:
594 LOGW("Connection Failure peer agent rejected");
597 case SAP_CONNECTION_FAILURE_UNKNOWN:
598 LOGW("Connection Failure peer agent unknown");
601 case SAP_CONNECTION_IN_PROGRESS:
602 LOGW("Connection in progress");
605 case SAP_CONNECTION_PEER_AGENT_NOT_SUPPORTED:
606 LOGW("Connection peer agent not supported");
612 _create_service_connection(gpointer user_data)
614 sap_info_s *priv = (sap_info_s *)user_data;
615 int result = sap_agent_request_service_connection(priv->agent,
617 _on_service_connection_created,
620 LOGD("request connection result : %d", result);
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,
631 sap_info_s *priv = (sap_info_s *)user_data;
635 case SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED:
636 LOGW("SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED");
639 case SAP_PEER_AGENT_FOUND_RESULT_FOUND:
640 if (peer_status == SAP_PEER_AGENT_STATUS_AVAILABLE)
642 LOGD("SAP_PEER_AGENT_FOUND_RESULT_FOUND");
643 priv->peer_agent = peer_agent;
644 g_idle_add(_create_service_connection, priv);
648 sap_peer_agent_destroy(peer_agent);
652 case SAP_PEER_AGENT_FOUND_RESULT_SERVICE_NOT_FOUND:
653 LOGW("SAP_PEER_AGENT_FOUND_RESULT_SERVICE_NOT_FOUND");
656 case SAP_PEER_AGENT_FOUND_RESULT_TIMEDOUT:
657 LOGW("SAP_PEER_AGENT_FOUND_RESULT_TIMEDOUT");
660 case SAP_PEER_AGENT_FOUND_RESULT_INTERNAL_ERROR:
661 LOGW("SAP_PEER_AGENT_FOUND_RESULT_INTERNAL_ERROR");
670 _find_peer_agent(gpointer user_data)
672 sap_info_s *priv = (sap_info_s *)user_data;
673 sap_agent_find_peer_agent(priv->agent, _on_peer_agent_updated, priv);
678 static void on_agent_initialized(sap_agent_h agent,
679 sap_agent_initialized_result_e result,
683 case SAP_AGENT_INITIALIZED_RESULT_SUCCESS:
684 LOGD("agent is initialized");
686 priv_data.agent = agent;
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);
692 case SAP_AGENT_INITIALIZED_RESULT_DUPLICATED:
693 LOGE("duplicate registration");
695 case SAP_AGENT_INITIALIZED_RESULT_INVALID_ARGUMENTS:
696 LOGE("invalid arguments");
698 case SAP_AGENT_INITIALIZED_RESULT_INTERNAL_ERROR:
699 LOGE("internal sap error");
702 LOGE("unknown status (%d)", result);
707 static void on_agent_deinitialized(sap_agent_h agent,
708 sap_agent_deinitialized_result_e result,
711 LOGD("result of deinitialize : %d", result);
714 static void _on_device_status_changed(sap_device_status_e status,
715 sap_transport_type_e transport_type,
718 LOGD("%s, status :%d", __func__, status);
720 switch (transport_type) {
721 case SAP_TRANSPORT_TYPE_BT:
722 LOGD("transport_type (%d): bt", transport_type);
724 case SAP_TRANSPORT_TYPE_BLE:
725 LOGD("transport_type (%d): ble", transport_type);
727 case SAP_TRANSPORT_TYPE_TCP:
728 LOGD("transport_type (%d): tcp/ip", transport_type);
730 case SAP_TRANSPORT_TYPE_USB:
731 LOGD("transport_type (%d): usb", transport_type);
733 case SAP_TRANSPORT_TYPE_MOBILE:
734 LOGD("transport_type (%d): mobile", transport_type);
737 LOGE("unknown transport_type (%d)", transport_type);
742 case SAP_DEVICE_STATUS_DETACHED:
743 LOGD("device is not connected.");
745 case SAP_DEVICE_STATUS_ATTACHED:
746 LOGD("Attached calling find peer now");
747 g_idle_add(_find_peer_agent, &priv_data);
750 LOGE("unknown status (%d)", status);
755 gboolean agent_initialize()
760 result = sap_agent_initialize(priv_data.agent, ACCESSORY_SERVICE_PROFILE_ID, SAP_AGENT_ROLE_CONSUMER,
761 on_agent_initialized, NULL);
763 LOGD("SAP >>> getRegisteredServiceAgent() >>> %d", result);
764 } while (result != SAP_RESULT_SUCCESS);
769 gboolean initialize_sap(void)
771 sap_agent_h agent = NULL;
773 sap_agent_create(&agent);
775 priv_data.agent = agent;
779 sap_set_device_status_changed_cb(_on_device_status_changed, NULL);
784 void deinitialize_sap(void)
786 if (priv_data.agent) {
787 int ret = sap_agent_deinitialize(priv_data.agent, on_agent_deinitialized, NULL);
789 case SAP_RESULT_FAILURE:
790 LOGW("Failed to deinitialize");
792 case SAP_RESULT_SUCCESS:
793 LOGD("Succeed to deinitialize");
795 case SAP_RESULT_PERMISSION_DENIED:
796 LOGW("permission denied: deinitialize ");
799 LOGD("deinitialize : %d", ret);
803 sap_agent_destroy(priv_data.agent);
804 priv_data.agent = NULL;