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>
37 #include "sticker_info.h"
40 #define ACCESSORY_SERVICE_PROFILE_ID "/sample/filetransfersender"
41 #define ACCESSORY_SERVICE_CHANNEL_ID 107
43 #define STICKER_SYNC_START_REQ "sticker-sync-start-req"
44 #define STICKER_SYNC_START_RSP "sticker-sync-start-rsp"
45 #define STICKER_SEND_START_REQ "sticker-send-start-req"
46 #define STICKER_SEND_START_RSP "sticker-send-start-rsp"
47 #define STICKER_SEND_FACE_DATA "sticker-send-face-data"
48 #define STICKER_SEND_STOP_REQ "sticker-send-stop-req"
49 #define STICKER_SEND_STOP_RSP "sticker-send-stop-rsp"
56 sap_peer_agent_h peer_agent;
57 sap_file_transaction_h file_socket;
66 static void _reset_sticker_data();
77 _reset_sticker_data();
81 static struct sap_info_s priv_data = { 0 };
82 static struct sticker_info sticker_data;
83 static struct sync_request pending_sync_request;
86 SYNC_START_RSP_SUCCESS = 1000,
87 SYNC_START_RSP_NO_STICKER = 1001,
88 SYNC_START_RSP_EXIST_STICKER = 1002
91 gboolean file_on_progress = 0;
92 static string incoming_file_name;
94 static int rec_file_cnt = 0;
95 static int total_file_count = 0;
97 static gboolean _send_json_data(JsonObject *obj)
99 JsonGenerator *j_generator = NULL;
100 JsonNode *j_node = NULL;
105 j_generator = json_generator_new();
106 if (j_generator == NULL) {
107 LOGE("Unable to json_generator_new");
111 j_node = json_node_new(JSON_NODE_OBJECT);
112 if (j_node == NULL) {
113 LOGE("Unable to json_node_new");
117 json_node_set_object(j_node, obj);
118 json_generator_set_root(j_generator, j_node);
120 data = json_generator_to_data(j_generator, &size);
122 LOGE("Unable to json_generator_to_data");
126 if (priv_data.socket) {
127 LOGD("Send JSON data : %s", data);
128 result = sap_socket_send_data(priv_data.socket, ACCESSORY_SERVICE_CHANNEL_ID, strlen(data), (void *)data);
136 json_node_free(j_node);
139 g_object_unref(j_generator);
141 return result ? FALSE : TRUE;
144 static void notify_sync_progress(unsigned int file_progress)
146 if (total_file_count == 0)
149 double total_progress = (((double)rec_file_cnt / (double)total_file_count) + (1.0/(double)total_file_count*file_progress/100))*100;
151 LOGI("(%2d / %2d), file progress : %3u%%, total progress : %3u%%", rec_file_cnt, total_file_count, file_progress, (unsigned int)total_progress);
152 char progress_str[32];
153 snprintf(progress_str, sizeof(progress_str), "%u", (unsigned int)total_progress);
154 send_message("sync_progress", progress_str);
157 static void _on_send_completed(sap_file_transaction_h file_transaction,
158 sap_ft_transfer_e result,
159 const char *file_path,
162 if (priv_data.file_socket) {
163 sap_file_transfer_destroy(file_transaction);
164 priv_data.file_socket = NULL;
167 if (result == SAP_FT_TRANSFER_SUCCESS) {
168 LOGI("Transfer Completed");
170 if (chmod(sticker_data.file_path.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
171 LOGE("Failed to change permission : %s. error : %s", sticker_data.file_path.c_str(), strerror(errno));
174 LOGI("Succeed to change permission : %s", sticker_data.file_path.c_str());
175 if (create_sticker_provider_handle() == STICKER_ERROR_NONE) {
176 insert_sticker_data(sticker_data.file_path.c_str(), sticker_data.keyword.c_str(), sticker_data.group.c_str(), sticker_data.description.c_str());
177 destroy_sticker_provider_handle();
179 if (unlink(sticker_data.file_path.c_str()) == -1)
180 LOGE("Failed to remove sticker file");
187 case (SAP_FT_TRANSFER_FAIL_CHANNEL_IO): {
188 LOGW("Channel IO Error.");
192 case (SAP_FT_TRANSFER_FAIL_FILE_IO): {
193 LOGW("File IO Error.");
197 case (SAP_FT_TRANSFER_FAIL_CMD_DROPPED):
199 LOGW("Transfer dropped.");
203 case (SAP_FT_TRANSFER_FAIL_PEER_UNRESPONSIVE):
205 LOGW("Peer Un Responsive.");
209 case (SAP_FT_TRANSFER_FAIL_PEER_CONN_LOST):
211 LOGW("Connection Lost.");
215 case (SAP_FT_TRANSFER_FAIL_PEER_CANCELLED):
217 LOGW("Peer Cancelled.");
221 case (SAP_FT_TRANSFER_FAIL_SPACE_NOT_AVAILABLE):
228 LOGW("Unknown Error");
233 file_on_progress = 0;
236 static void _on_sending_file_in_progress(sap_file_transaction_h file_transaction,
237 unsigned short int percentage_progress,
240 notify_sync_progress(percentage_progress);
243 static void __set_file_transfer_cb(sap_file_transaction_h file_socket)
245 LOGI("# set callbacks");
246 sap_file_transfer_set_progress_cb(file_socket, _on_sending_file_in_progress, NULL);
248 sap_file_transfer_set_done_cb(file_socket, _on_send_completed, NULL);
254 char file_path[PATH_MAX];
255 char *data_path = NULL;
257 data_path = app_get_shared_data_path();
258 LOGI("Path : %s", data_path);
259 sprintf(file_path, "%s/%s", data_path, incoming_file_name.c_str());
260 LOGI("Receive filepath : %s", file_path);
261 sticker_data.file_path = string(file_path);
264 ret = sap_file_transfer_receive(priv_data.file_socket, file_path);
266 case SAP_RESULT_PERMISSION_DENIED:
267 LOGW("permission denied");
269 case SAP_RESULT_FAILURE:
272 case SAP_RESULT_SUCCESS:
277 file_on_progress = 1;
280 void sap_file_transfer_get_receive_filepath(char **filepath)
282 *filepath = strdup(sticker_data.file_path.c_str());
285 void request_sticker_data(const char *mode, const char *category, const char *type)
287 JsonObject *j_object = json_object_new();
288 if (j_object == NULL) {
289 LOGE("json object create error");
293 json_object_set_string_member(j_object, "msgId", STICKER_SYNC_START_REQ);
294 json_object_set_int_member(j_object, "tID", ++t_id);
295 json_object_set_string_member(j_object, "mode", mode);
296 json_object_set_string_member(j_object, "category", category);
297 json_object_set_string_member(j_object, "type", type);
299 if (_send_json_data(j_object) == FALSE) {
300 pending_sync_request.mode = string(mode ? mode : "manual");
301 pending_sync_request.category = string(category? category : "arsticker");
302 pending_sync_request.type = string(type ? type : "input");
304 LOGI("Push sync request");
307 json_object_unref(j_object);
312 int ret = sap_file_transfer_reject(priv_data.file_socket);
313 LOGI("ret : %d", ret);
315 file_on_progress = 0;
318 static void _on_receive_file_cb(sap_peer_agent_h peer_agent_h,
319 sap_file_transaction_h socket,
320 const char *file_path,
323 file_on_progress = 1;
324 priv_data.file_socket = socket;
325 LOGI("# incoming file request.");
326 __set_file_transfer_cb(priv_data.file_socket);
328 incoming_file_name = file_path;
329 std::size_t found = incoming_file_name.find_last_of("/");
330 incoming_file_name = incoming_file_name.substr(found+1);
332 LOGI("# file path : %s, incoming file name : %s", file_path, incoming_file_name.c_str());
337 void conn_terminated(sap_peer_agent_h peer_agent,
339 sap_service_connection_terminated_reason_e result,
342 sap_info_s *priv = NULL;
343 priv = (sap_info_s *)user_data;
347 case SAP_CONNECTION_TERMINATED_REASON_PEER_DISCONNECTED:
348 LOGW("Peer Disconnected");
350 case SAP_CONNECTION_TERMINATED_REASON_DEVICE_DETACHED:
351 LOGW("Disconnected Device Detached");
353 case SAP_CONNECTION_TERMINATED_REASON_UNKNOWN:
354 LOGW("Disconnected Unknown Reason");
357 LOGW("connection terminated. reason : %d", result);
361 sap_socket_destroy(priv->socket);
367 static void _reset_sticker_data()
369 sticker_data.file_path.clear();
370 sticker_data.group.clear();
371 sticker_data.keyword.clear();
372 sticker_data.disp_type.clear();
373 sticker_data.description.clear();
377 on_data_received(sap_socket_h socket, unsigned short int channel_id, unsigned int payload_length, void *buffer,
378 void *user_data) /* message exchange on_receive callback (sap_agent_data_received_cb) */
380 LOGI("received data: %s, len:%d", (char *)buffer, payload_length);
382 JsonParser *parser = json_parser_new();
383 GError *err_msg = NULL;
384 JsonNode *root = NULL;
385 JsonObject *root_obj = NULL;
387 const char *json_msgid = NULL;
389 json_parser_load_from_data(parser, (char *)buffer, -1, &err_msg);
391 LOGE("failed to load json file. error message: %s", err_msg->message);
395 root = json_parser_get_root(parser);
397 LOGE("failed to get root");
401 root_obj = json_node_get_object(root);
402 if (root_obj == NULL) {
403 LOGE("failed to get object");
407 json_msgid = json_object_get_string_member(root_obj, "msgId");
408 msg_id = string(json_msgid ? json_msgid : "");
409 if (msg_id == STICKER_SYNC_START_RSP) {
410 LOGD("msg : %s", msg_id.c_str());
411 const char *json_result = json_object_get_string_member(root_obj, "result");
412 string result = string(json_result ? json_result : "");
413 int result_code = json_object_get_int_member(root_obj, "resultCode");
414 LOGD("result : %s, resultCode : %d", result.c_str(), result_code);
416 string response_to_app;
417 switch (result_code) {
418 case SYNC_START_RSP_SUCCESS:
419 case SYNC_START_RSP_EXIST_STICKER:
420 response_to_app = "success";
422 case SYNC_START_RSP_NO_STICKER:
423 response_to_app = "no_sticker";
426 response_to_app = "unknown_error";
430 send_message("sync_start_response", response_to_app.c_str());
431 } else if (msg_id == STICKER_SEND_START_REQ) {
432 LOGD("msg : %s", msg_id.c_str());
433 total_file_count = 0;
435 t_id = json_object_get_int_member(root_obj, "tID");
436 JsonArray *file_list = json_object_get_array_member(root_obj, "list");
438 int arr_len = json_array_get_length(file_list);
439 for (int i = 0; i < arr_len; i++) {
440 JsonObject *file_obj = json_array_get_object_element(file_list, i);
441 int file_len = json_object_get_int_member(file_obj, "size");
442 const char *json_filename = json_object_get_string_member(file_obj, "fileName");
443 if (!json_filename) {
444 json_filename = json_object_get_string_member(file_obj, "filename");
446 string file_name = string(json_filename ? json_filename : "");
449 LOGD("Add file : %s, len : %d", file_name.c_str(), file_len);
452 LOGD("Delete file : %s, len : %d", file_name.c_str(), file_len);
453 if (create_sticker_provider_handle() == STICKER_ERROR_NONE) {
454 delete_sticker_data(file_name.c_str());
455 destroy_sticker_provider_handle();
461 JsonObject *j_object = json_object_new();
462 if (j_object == NULL) {
463 LOGE("Unable to json_object_new");
467 json_object_set_string_member(j_object, "msgId", STICKER_SEND_START_RSP);
468 json_object_set_int_member(j_object, "tID", t_id);
469 json_object_set_string_member(j_object, "result", "success");
471 if (_send_json_data(j_object) == FALSE)
472 LOGE("Failed to send message");
474 json_object_unref(j_object);
475 } else if (msg_id == STICKER_SEND_FACE_DATA) {
476 LOGD("msg : %s", msg_id.c_str());
477 _reset_sticker_data();
479 const char *type_data = json_object_get_string_member(root_obj, "type");
481 sticker_data.disp_type = string(type_data);
483 const char *category = json_object_get_string_member(root_obj, "category");
485 sticker_data.group = string(category);
486 sticker_data.keyword = string(category);
488 } else if (msg_id == STICKER_SEND_STOP_REQ) {
489 LOGD("msg : %s", msg_id.c_str());
490 const char *json_reason = json_object_get_string_member(root_obj, "reason");
491 string reason = string(json_reason ? json_reason : "");
492 int file_len = json_object_get_int_member(root_obj, "count");
494 JsonObject *j_object = json_object_new();
495 if (j_object == NULL) {
496 LOGE("Unable to json_object_new");
500 json_object_set_string_member(j_object, "msgId", STICKER_SEND_STOP_RSP);
501 json_object_set_int_member(j_object, "tID", t_id);
503 if (reason == "complete" && rec_file_cnt != file_len)
504 json_object_set_string_member(j_object, "result", "failure");
506 int complete_flags = 0;
507 if (vconf_get_int(VCONFKEY_STICKER_SYNC_COMPLETE, &complete_flags) == 0) {
508 if (sticker_data.group == string("arsticker"))
509 complete_flags |= 0x1;
510 else if (sticker_data.group == string("bitmoji"))
511 complete_flags |= 0x2;
513 LOGD("sync complete flag : %x", complete_flags);
515 if (vconf_set_int(VCONFKEY_STICKER_SYNC_COMPLETE, complete_flags) == 0)
516 LOGD("Succeed to set sync complete");
518 LOGW("Fail to set sync complete");
521 LOGW("Failed to get sticker sync flags");
524 json_object_set_string_member(j_object, "result", "success");
527 if (_send_json_data(j_object) == FALSE)
528 LOGE("Failed to send message");
530 send_message("sync_stop_result", reason.c_str());
532 json_object_unref(j_object);
534 LOGW("unknown msg id : %s", msg_id.c_str());
538 g_error_free(err_msg);
541 g_object_unref(parser);
544 static void on_conn_req(sap_peer_agent_h peer_agent,
546 sap_service_connection_result_e result,
551 case SAP_CONNECTION_SUCCESS:
552 LOGI("Connection success");
553 priv_data.socket = socket;
554 sap_peer_agent_accept_service_connection(peer_agent);
555 sap_peer_agent_set_service_connection_terminated_cb(peer_agent, conn_terminated, &priv_data);
556 sap_socket_set_data_received_cb(socket, on_data_received, peer_agent);
558 case SAP_CONNECTION_ALREADY_EXIST:
559 priv_data.socket = socket;
560 LOGI("Connection Already Exist");
562 case SAP_CONNECTION_FAILURE_DEVICE_UNREACHABLE:
563 LOGW("Connection failure device unreachable");
565 case SAP_CONNECTION_FAILURE_INVALID_PEERAGENT:
566 LOGW("Connection failure invalid peer agent");
568 case SAP_CONNECTION_FAILURE_NETWORK:
569 LOGW("Connection failure network");
571 case SAP_CONNECTION_FAILURE_PEERAGENT_NO_RESPONSE:
572 LOGW("Connection failure peer agent no response");
574 case SAP_CONNECTION_FAILURE_PEERAGENT_REJECTED:
575 LOGW("Connection failure peer agent rejected");
577 case SAP_CONNECTION_FAILURE_UNKNOWN:
578 LOGW("Connection failure unknown");
581 LOGW("Connection failure. error code : %d", result);
587 _on_service_connection_created(sap_peer_agent_h peer_agent,
589 sap_service_connection_result_e result,
592 sap_info_s *priv = (sap_info_s *)user_data;
596 case SAP_CONNECTION_SUCCESS:
597 sap_peer_agent_set_service_connection_terminated_cb(priv->peer_agent,
601 sap_socket_set_data_received_cb(socket, on_data_received, peer_agent);
602 priv->socket = socket;
603 LOGI("Connection Established");
605 if (!pending_sync_request.mode.empty()) {
606 LOGD("[Request to sync sticker] mode: %s, category: %s, type : %s", pending_sync_request.mode.c_str(),
607 pending_sync_request.category.c_str(),
608 pending_sync_request.type.c_str());
610 request_sticker_data(pending_sync_request.mode.c_str(), pending_sync_request.category.c_str(), pending_sync_request.type.c_str());
611 pending_sync_request.mode.clear();
612 pending_sync_request.category.clear();
613 pending_sync_request.type.clear();
618 case SAP_CONNECTION_ALREADY_EXIST:
619 priv->socket = socket;
620 LOGI("Connection Already Exist");
623 case SAP_CONNECTION_FAILURE_DEVICE_UNREACHABLE:
624 LOGW("Connection Failure device unreachable");
627 case SAP_CONNECTION_FAILURE_INVALID_PEERAGENT:
628 LOGW("Connection Failure invalid peer agent");
631 case SAP_CONNECTION_FAILURE_NETWORK:
632 LOGW("Connection Failure network");
635 case SAP_CONNECTION_FAILURE_PEERAGENT_NO_RESPONSE:
636 LOGW("Connection Failure peer agent no response");
639 case SAP_CONNECTION_FAILURE_PEERAGENT_REJECTED:
640 LOGW("Connection Failure peer agent rejected");
643 case SAP_CONNECTION_FAILURE_UNKNOWN:
644 LOGW("Connection Failure peer agent unknown");
647 case SAP_CONNECTION_IN_PROGRESS:
648 LOGW("Connection in progress");
651 case SAP_CONNECTION_PEER_AGENT_NOT_SUPPORTED:
652 LOGW("Connection peer agent not supported");
658 _create_service_connection(gpointer user_data)
660 sap_info_s *priv = (sap_info_s *)user_data;
661 int result = sap_agent_request_service_connection(priv->agent,
663 _on_service_connection_created,
666 LOGD("request connection result : %d", result);
672 _on_peer_agent_updated(sap_peer_agent_h peer_agent,
673 sap_peer_agent_status_e peer_status,
674 sap_peer_agent_found_result_e result,
677 sap_info_s *priv = (sap_info_s *)user_data;
681 case SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED:
682 LOGW("SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED");
685 case SAP_PEER_AGENT_FOUND_RESULT_FOUND:
686 if (peer_status == SAP_PEER_AGENT_STATUS_AVAILABLE)
688 LOGD("SAP_PEER_AGENT_FOUND_RESULT_FOUND");
689 priv->peer_agent = peer_agent;
690 g_idle_add(_create_service_connection, priv);
694 sap_peer_agent_destroy(peer_agent);
698 case SAP_PEER_AGENT_FOUND_RESULT_SERVICE_NOT_FOUND:
699 LOGW("SAP_PEER_AGENT_FOUND_RESULT_SERVICE_NOT_FOUND");
702 case SAP_PEER_AGENT_FOUND_RESULT_TIMEDOUT:
703 LOGW("SAP_PEER_AGENT_FOUND_RESULT_TIMEDOUT");
706 case SAP_PEER_AGENT_FOUND_RESULT_INTERNAL_ERROR:
707 LOGW("SAP_PEER_AGENT_FOUND_RESULT_INTERNAL_ERROR");
716 _find_peer_agent(gpointer user_data)
718 sap_info_s *priv = (sap_info_s *)user_data;
719 sap_agent_find_peer_agent(priv->agent, _on_peer_agent_updated, priv);
724 static void on_agent_initialized(sap_agent_h agent,
725 sap_agent_initialized_result_e result,
729 case SAP_AGENT_INITIALIZED_RESULT_SUCCESS:
730 LOGD("agent is initialized");
732 priv_data.agent = agent;
734 sap_file_transfer_set_incoming_file_cb(agent, _on_receive_file_cb, NULL);
735 sap_agent_set_service_connection_requested_cb(agent, on_conn_req, NULL);
738 case SAP_AGENT_INITIALIZED_RESULT_DUPLICATED:
739 LOGE("duplicate registration");
741 case SAP_AGENT_INITIALIZED_RESULT_INVALID_ARGUMENTS:
742 LOGE("invalid arguments");
744 case SAP_AGENT_INITIALIZED_RESULT_INTERNAL_ERROR:
745 LOGE("internal sap error");
748 LOGE("unknown status (%d)", result);
753 static void on_agent_deinitialized(sap_agent_h agent,
754 sap_agent_deinitialized_result_e result,
757 LOGD("result of deinitialize : %d", result);
760 static void _on_device_status_changed(sap_device_status_e status,
761 sap_transport_type_e transport_type,
764 LOGD("%s, status :%d", __func__, status);
766 switch (transport_type) {
767 case SAP_TRANSPORT_TYPE_BT:
768 LOGD("transport_type (%d): bt", transport_type);
770 case SAP_TRANSPORT_TYPE_BLE:
771 LOGD("transport_type (%d): ble", transport_type);
773 case SAP_TRANSPORT_TYPE_TCP:
774 LOGD("transport_type (%d): tcp/ip", transport_type);
776 case SAP_TRANSPORT_TYPE_USB:
777 LOGD("transport_type (%d): usb", transport_type);
779 case SAP_TRANSPORT_TYPE_MOBILE:
780 LOGD("transport_type (%d): mobile", transport_type);
783 LOGE("unknown transport_type (%d)", transport_type);
788 case SAP_DEVICE_STATUS_DETACHED:
789 LOGD("device is not connected.");
791 case SAP_DEVICE_STATUS_ATTACHED:
792 LOGD("Attached calling find peer now");
793 g_idle_add(_find_peer_agent, &priv_data);
796 LOGE("unknown status (%d)", status);
801 gboolean agent_initialize()
806 result = sap_agent_initialize(priv_data.agent, ACCESSORY_SERVICE_PROFILE_ID, SAP_AGENT_ROLE_CONSUMER,
807 on_agent_initialized, NULL);
809 LOGD("SAP >>> getRegisteredServiceAgent() >>> %d", result);
810 } while (result != SAP_RESULT_SUCCESS);
815 gboolean initialize_sap(void)
817 sap_agent_h agent = NULL;
819 sap_agent_create(&agent);
821 priv_data.agent = agent;
825 sap_set_device_status_changed_cb(_on_device_status_changed, NULL);
830 void deinitialize_sap(void)
832 if (priv_data.agent) {
833 int ret = sap_agent_deinitialize(priv_data.agent, on_agent_deinitialized, NULL);
835 case SAP_RESULT_FAILURE:
836 LOGW("Failed to deinitialize");
838 case SAP_RESULT_SUCCESS:
839 LOGD("Succeed to deinitialize");
841 case SAP_RESULT_PERMISSION_DENIED:
842 LOGW("permission denied: deinitialize ");
845 LOGD("deinitialize : %d", ret);
849 sap_agent_destroy(priv_data.agent);
850 priv_data.agent = NULL;