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"
39 #include "sync_alarm.h"
41 #define ACCESSORY_SERVICE_PROFILE_ID "/sample/filetransfersender"
42 #define ACCESSORY_SERVICE_CHANNEL_ID 107
44 #define STICKER_SYNC_START_REQ "sticker-sync-start-req"
45 #define STICKER_SYNC_START_RSP "sticker-sync-start-rsp"
46 #define STICKER_SEND_START_REQ "sticker-send-start-req"
47 #define STICKER_SEND_START_RSP "sticker-send-start-rsp"
48 #define STICKER_SEND_FACE_DATA "sticker-send-face-data"
49 #define STICKER_SEND_STOP_REQ "sticker-send-stop-req"
50 #define STICKER_SEND_STOP_RSP "sticker-send-stop-rsp"
57 sap_peer_agent_h peer_agent;
58 sap_file_transaction_h file_socket;
67 static void _reset_sticker_data();
78 _reset_sticker_data();
82 static struct sap_info_s priv_data = { 0 };
83 static struct sticker_info sticker_data;
84 static struct sync_request pending_sync_request, current_sync_request;
87 SYNC_START_RSP_SUCCESS = 1000,
88 SYNC_START_RSP_NO_STICKER = 1001,
89 SYNC_START_RSP_EXIST_STICKER = 1002
92 gboolean file_on_progress = 0;
93 static string incoming_file_name;
95 static int rec_file_cnt = 0;
96 static int total_file_count = 0;
98 static gboolean _send_json_data(JsonObject *obj)
100 JsonGenerator *j_generator = NULL;
101 JsonNode *j_node = NULL;
106 j_generator = json_generator_new();
107 if (j_generator == NULL) {
108 LOGE("Unable to json_generator_new");
112 j_node = json_node_new(JSON_NODE_OBJECT);
113 if (j_node == NULL) {
114 LOGE("Unable to json_node_new");
118 json_node_set_object(j_node, obj);
119 json_generator_set_root(j_generator, j_node);
121 data = json_generator_to_data(j_generator, &size);
123 LOGE("Unable to json_generator_to_data");
127 if (priv_data.socket) {
128 LOGD("Send JSON data : %s", data);
129 result = sap_socket_send_data(priv_data.socket, ACCESSORY_SERVICE_CHANNEL_ID, strlen(data), (void *)data);
137 json_node_free(j_node);
140 g_object_unref(j_generator);
142 return result ? FALSE : TRUE;
145 static void notify_sync_progress(unsigned int file_progress)
147 if (total_file_count == 0)
150 double total_progress = (((double)rec_file_cnt / (double)total_file_count) + (1.0/(double)total_file_count*file_progress/100))*100;
152 LOGI("(%2d / %2d), file progress : %3u%%, total progress : %3u%%", rec_file_cnt, total_file_count, file_progress, (unsigned int)total_progress);
153 char progress_str[32];
154 snprintf(progress_str, sizeof(progress_str), "%u", (unsigned int)total_progress);
155 send_message("sync_progress", progress_str);
158 static void _on_send_completed(sap_file_transaction_h file_transaction,
159 sap_ft_transfer_e result,
160 const char *file_path,
163 if (priv_data.file_socket) {
164 sap_file_transfer_destroy(file_transaction);
165 priv_data.file_socket = NULL;
168 if (result == SAP_FT_TRANSFER_SUCCESS) {
169 LOGI("Transfer Completed");
171 if (chmod(sticker_data.file_path.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
172 LOGE("Failed to change permission : %s. error : %s", sticker_data.file_path.c_str(), strerror(errno));
175 LOGI("Succeed to change permission : %s", sticker_data.file_path.c_str());
176 if (create_sticker_provider_handle() == STICKER_ERROR_NONE) {
177 insert_sticker_data(sticker_data.file_path.c_str(), sticker_data.keyword.c_str(), sticker_data.group.c_str(), sticker_data.description.c_str());
178 destroy_sticker_provider_handle();
180 if (unlink(sticker_data.file_path.c_str()) == -1)
181 LOGE("Failed to remove sticker file");
188 case (SAP_FT_TRANSFER_FAIL_CHANNEL_IO): {
189 LOGW("Channel IO Error.");
193 case (SAP_FT_TRANSFER_FAIL_FILE_IO): {
194 LOGW("File IO Error.");
198 case (SAP_FT_TRANSFER_FAIL_CMD_DROPPED):
200 LOGW("Transfer dropped.");
204 case (SAP_FT_TRANSFER_FAIL_PEER_UNRESPONSIVE):
206 LOGW("Peer Un Responsive.");
210 case (SAP_FT_TRANSFER_FAIL_PEER_CONN_LOST):
212 LOGW("Connection Lost.");
216 case (SAP_FT_TRANSFER_FAIL_PEER_CANCELLED):
218 LOGW("Peer Cancelled.");
222 case (SAP_FT_TRANSFER_FAIL_SPACE_NOT_AVAILABLE):
229 LOGW("Unknown Error");
234 file_on_progress = 0;
237 static void _on_sending_file_in_progress(sap_file_transaction_h file_transaction,
238 unsigned short int percentage_progress,
241 notify_sync_progress(percentage_progress);
244 static void __set_file_transfer_cb(sap_file_transaction_h file_socket)
246 LOGI("# set callbacks");
247 sap_file_transfer_set_progress_cb(file_socket, _on_sending_file_in_progress, NULL);
249 sap_file_transfer_set_done_cb(file_socket, _on_send_completed, NULL);
255 char file_path[PATH_MAX];
256 char *data_path = NULL;
258 data_path = app_get_shared_data_path();
259 LOGI("Path : %s", data_path);
260 sprintf(file_path, "%s/%s", data_path, incoming_file_name.c_str());
261 LOGI("Receive filepath : %s", file_path);
262 sticker_data.file_path = string(file_path);
265 ret = sap_file_transfer_receive(priv_data.file_socket, file_path);
267 case SAP_RESULT_PERMISSION_DENIED:
268 LOGW("permission denied");
270 case SAP_RESULT_FAILURE:
273 case SAP_RESULT_SUCCESS:
278 file_on_progress = 1;
281 void sap_file_transfer_get_receive_filepath(char **filepath)
283 *filepath = strdup(sticker_data.file_path.c_str());
286 void request_sticker_data(const char *mode, const char *category, const char *type)
288 JsonObject *j_object = json_object_new();
289 if (j_object == NULL) {
290 LOGE("json object create error");
294 json_object_set_string_member(j_object, "msgId", STICKER_SYNC_START_REQ);
295 json_object_set_int_member(j_object, "tID", ++t_id);
296 json_object_set_string_member(j_object, "mode", mode);
297 json_object_set_string_member(j_object, "category", category);
298 json_object_set_string_member(j_object, "type", type);
300 if (_send_json_data(j_object) == FALSE) {
301 pending_sync_request.mode = string(mode ? mode : "manual");
302 pending_sync_request.category = string(category? category : "arsticker");
303 pending_sync_request.type = string(type ? type : "input");
305 LOGI("Push sync request");
308 current_sync_request.mode = string(mode ? mode : "manual");
309 current_sync_request.category = string(category? category : "arsticker");
310 current_sync_request.type = string(type ? type : "input");
313 json_object_unref(j_object);
318 int ret = sap_file_transfer_reject(priv_data.file_socket);
319 LOGI("ret : %d", ret);
321 file_on_progress = 0;
324 static void _on_receive_file_cb(sap_peer_agent_h peer_agent_h,
325 sap_file_transaction_h socket,
326 const char *file_path,
329 file_on_progress = 1;
330 priv_data.file_socket = socket;
331 LOGI("# incoming file request.");
332 __set_file_transfer_cb(priv_data.file_socket);
334 incoming_file_name = file_path;
335 std::size_t found = incoming_file_name.find_last_of("/");
336 incoming_file_name = incoming_file_name.substr(found+1);
338 LOGI("# file path : %s, incoming file name : %s", file_path, incoming_file_name.c_str());
343 void conn_terminated(sap_peer_agent_h peer_agent,
345 sap_service_connection_terminated_reason_e result,
348 sap_info_s *priv = NULL;
349 priv = (sap_info_s *)user_data;
353 case SAP_CONNECTION_TERMINATED_REASON_PEER_DISCONNECTED:
354 LOGW("Peer Disconnected");
356 case SAP_CONNECTION_TERMINATED_REASON_DEVICE_DETACHED:
357 LOGW("Disconnected Device Detached");
359 case SAP_CONNECTION_TERMINATED_REASON_UNKNOWN:
360 LOGW("Disconnected Unknown Reason");
363 LOGW("connection terminated. reason : %d", result);
367 sap_socket_destroy(priv->socket);
373 static void _reset_sticker_data()
375 sticker_data.file_path.clear();
376 sticker_data.group.clear();
377 sticker_data.keyword.clear();
378 sticker_data.disp_type.clear();
379 sticker_data.description.clear();
383 on_data_received(sap_socket_h socket, unsigned short int channel_id, unsigned int payload_length, void *buffer,
384 void *user_data) /* message exchange on_receive callback (sap_agent_data_received_cb) */
386 LOGI("received data: %s, len:%d", (char *)buffer, payload_length);
388 JsonParser *parser = json_parser_new();
389 GError *err_msg = NULL;
390 JsonNode *root = NULL;
391 JsonObject *root_obj = NULL;
393 const char *json_msgid = NULL;
395 json_parser_load_from_data(parser, (char *)buffer, -1, &err_msg);
397 LOGE("failed to load json file. error message: %s", err_msg->message);
401 root = json_parser_get_root(parser);
403 LOGE("failed to get root");
407 root_obj = json_node_get_object(root);
408 if (root_obj == NULL) {
409 LOGE("failed to get object");
413 json_msgid = json_object_get_string_member(root_obj, "msgId");
414 msg_id = string(json_msgid ? json_msgid : "");
415 if (msg_id == STICKER_SYNC_START_RSP) {
416 LOGD("msg : %s", msg_id.c_str());
417 const char *json_result = json_object_get_string_member(root_obj, "result");
418 string result = string(json_result ? json_result : "");
419 int result_code = json_object_get_int_member(root_obj, "resultCode");
420 LOGD("result : %s, resultCode : %d", result.c_str(), result_code);
422 string response_to_app;
423 switch (result_code) {
424 case SYNC_START_RSP_SUCCESS:
425 case SYNC_START_RSP_EXIST_STICKER:
426 response_to_app = "success";
428 case SYNC_START_RSP_NO_STICKER:
429 response_to_app = "no_sticker";
432 response_to_app = "unknown_error";
436 send_message("sync_start_response", response_to_app.c_str());
437 } else if (msg_id == STICKER_SEND_START_REQ) {
438 LOGD("msg : %s", msg_id.c_str());
439 total_file_count = 0;
441 t_id = json_object_get_int_member(root_obj, "tID");
442 JsonArray *file_list = json_object_get_array_member(root_obj, "list");
444 int arr_len = json_array_get_length(file_list);
445 for (int i = 0; i < arr_len; i++) {
446 JsonObject *file_obj = json_array_get_object_element(file_list, i);
447 int file_len = json_object_get_int_member(file_obj, "size");
448 const char *json_filename = json_object_get_string_member(file_obj, "fileName");
449 if (!json_filename) {
450 json_filename = json_object_get_string_member(file_obj, "filename");
452 string file_name = string(json_filename ? json_filename : "");
455 LOGD("Add file : %s, len : %d", file_name.c_str(), file_len);
458 LOGD("Delete file : %s, len : %d", file_name.c_str(), file_len);
459 if (create_sticker_provider_handle() == STICKER_ERROR_NONE) {
460 delete_sticker_data(file_name.c_str());
461 destroy_sticker_provider_handle();
467 JsonObject *j_object = json_object_new();
468 if (j_object == NULL) {
469 LOGE("Unable to json_object_new");
473 json_object_set_string_member(j_object, "msgId", STICKER_SEND_START_RSP);
474 json_object_set_int_member(j_object, "tID", t_id);
475 json_object_set_string_member(j_object, "result", "success");
477 if (_send_json_data(j_object) == FALSE)
478 LOGE("Failed to send message");
480 json_object_unref(j_object);
481 } else if (msg_id == STICKER_SEND_FACE_DATA) {
482 LOGD("msg : %s", msg_id.c_str());
483 _reset_sticker_data();
485 const char *type_data = json_object_get_string_member(root_obj, "type");
487 sticker_data.disp_type = string(type_data);
489 const char *category = json_object_get_string_member(root_obj, "category");
491 sticker_data.group = string(category);
492 sticker_data.keyword = string(category);
494 } else if (msg_id == STICKER_SEND_STOP_REQ) {
495 LOGD("msg : %s", msg_id.c_str());
496 const char *json_reason = json_object_get_string_member(root_obj, "reason");
497 string reason = string(json_reason ? json_reason : "");
498 int file_len = json_object_get_int_member(root_obj, "count");
500 JsonObject *j_object = json_object_new();
501 if (j_object == NULL) {
502 LOGE("Unable to json_object_new");
506 json_object_set_string_member(j_object, "msgId", STICKER_SEND_STOP_RSP);
507 json_object_set_int_member(j_object, "tID", t_id);
509 if (reason == "complete" && rec_file_cnt != file_len)
510 json_object_set_string_member(j_object, "result", "failure");
512 int complete_flags = 0;
513 if (vconf_get_int(VCONFKEY_STICKER_SYNC_COMPLETE, &complete_flags) == 0) {
514 if (sticker_data.group == string("arsticker"))
515 complete_flags |= 0x1;
516 else if (sticker_data.group == string("bitmoji"))
517 complete_flags |= 0x2;
519 LOGD("sync complete flag : %x", complete_flags);
521 if (vconf_set_int(VCONFKEY_STICKER_SYNC_COMPLETE, complete_flags) == 0)
522 LOGD("Succeed to set sync complete");
524 LOGW("Fail to set sync complete");
527 LOGW("Failed to get sticker sync flags");
530 json_object_set_string_member(j_object, "result", "success");
532 if (current_sync_request.mode == string("oobe")) {
533 LOGD("alarm exist : %d", sync_alarm_exist());
534 sync_alarm_register(APP_CONTROL_OPERATION_SYNC_ALARM, SYNC_ALARM_DELAY, SYNC_ALARM_INTERVAL);
536 else if (current_sync_request.mode == string("manual")) {
537 if (!sync_alarm_exist())
538 sync_alarm_register(APP_CONTROL_OPERATION_SYNC_ALARM, SYNC_ALARM_DELAY, SYNC_ALARM_INTERVAL);
542 if (_send_json_data(j_object) == FALSE)
543 LOGE("Failed to send message");
545 send_message("sync_stop_result", reason.c_str());
547 json_object_unref(j_object);
549 current_sync_request.mode.clear();
550 current_sync_request.category.clear();
551 current_sync_request.type.clear();
553 LOGW("unknown msg id : %s", msg_id.c_str());
557 g_error_free(err_msg);
560 g_object_unref(parser);
563 static void on_conn_req(sap_peer_agent_h peer_agent,
565 sap_service_connection_result_e result,
570 case SAP_CONNECTION_SUCCESS:
571 LOGI("Connection success");
572 priv_data.socket = socket;
573 sap_peer_agent_accept_service_connection(peer_agent);
574 sap_peer_agent_set_service_connection_terminated_cb(peer_agent, conn_terminated, &priv_data);
575 sap_socket_set_data_received_cb(socket, on_data_received, peer_agent);
577 case SAP_CONNECTION_ALREADY_EXIST:
578 priv_data.socket = socket;
579 LOGI("Connection Already Exist");
581 case SAP_CONNECTION_FAILURE_DEVICE_UNREACHABLE:
582 LOGW("Connection failure device unreachable");
584 case SAP_CONNECTION_FAILURE_INVALID_PEERAGENT:
585 LOGW("Connection failure invalid peer agent");
587 case SAP_CONNECTION_FAILURE_NETWORK:
588 LOGW("Connection failure network");
590 case SAP_CONNECTION_FAILURE_PEERAGENT_NO_RESPONSE:
591 LOGW("Connection failure peer agent no response");
593 case SAP_CONNECTION_FAILURE_PEERAGENT_REJECTED:
594 LOGW("Connection failure peer agent rejected");
596 case SAP_CONNECTION_FAILURE_UNKNOWN:
597 LOGW("Connection failure unknown");
600 LOGW("Connection failure. error code : %d", result);
606 _on_service_connection_created(sap_peer_agent_h peer_agent,
608 sap_service_connection_result_e result,
611 sap_info_s *priv = (sap_info_s *)user_data;
615 case SAP_CONNECTION_SUCCESS:
616 sap_peer_agent_set_service_connection_terminated_cb(priv->peer_agent,
620 sap_socket_set_data_received_cb(socket, on_data_received, peer_agent);
621 priv->socket = socket;
622 LOGI("Connection Established");
624 if (!pending_sync_request.mode.empty()) {
625 LOGD("[Request to sync sticker] mode: %s, category: %s, type : %s", pending_sync_request.mode.c_str(),
626 pending_sync_request.category.c_str(),
627 pending_sync_request.type.c_str());
629 request_sticker_data(pending_sync_request.mode.c_str(), pending_sync_request.category.c_str(), pending_sync_request.type.c_str());
631 pending_sync_request.mode.clear();
632 pending_sync_request.category.clear();
633 pending_sync_request.type.clear();
638 case SAP_CONNECTION_ALREADY_EXIST:
639 priv->socket = socket;
640 LOGI("Connection Already Exist");
643 case SAP_CONNECTION_FAILURE_DEVICE_UNREACHABLE:
644 LOGW("Connection Failure device unreachable");
647 case SAP_CONNECTION_FAILURE_INVALID_PEERAGENT:
648 LOGW("Connection Failure invalid peer agent");
651 case SAP_CONNECTION_FAILURE_NETWORK:
652 LOGW("Connection Failure network");
655 case SAP_CONNECTION_FAILURE_PEERAGENT_NO_RESPONSE:
656 LOGW("Connection Failure peer agent no response");
659 case SAP_CONNECTION_FAILURE_PEERAGENT_REJECTED:
660 LOGW("Connection Failure peer agent rejected");
663 case SAP_CONNECTION_FAILURE_UNKNOWN:
664 LOGW("Connection Failure peer agent unknown");
667 case SAP_CONNECTION_IN_PROGRESS:
668 LOGW("Connection in progress");
671 case SAP_CONNECTION_PEER_AGENT_NOT_SUPPORTED:
672 LOGW("Connection peer agent not supported");
678 _create_service_connection(gpointer user_data)
680 sap_info_s *priv = (sap_info_s *)user_data;
681 int result = sap_agent_request_service_connection(priv->agent,
683 _on_service_connection_created,
686 LOGD("request connection result : %d", result);
692 _on_peer_agent_updated(sap_peer_agent_h peer_agent,
693 sap_peer_agent_status_e peer_status,
694 sap_peer_agent_found_result_e result,
697 sap_info_s *priv = (sap_info_s *)user_data;
701 case SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED:
702 LOGW("SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED");
705 case SAP_PEER_AGENT_FOUND_RESULT_FOUND:
706 if (peer_status == SAP_PEER_AGENT_STATUS_AVAILABLE)
708 LOGD("SAP_PEER_AGENT_FOUND_RESULT_FOUND");
709 priv->peer_agent = peer_agent;
710 g_idle_add(_create_service_connection, priv);
714 sap_peer_agent_destroy(peer_agent);
718 case SAP_PEER_AGENT_FOUND_RESULT_SERVICE_NOT_FOUND:
719 LOGW("SAP_PEER_AGENT_FOUND_RESULT_SERVICE_NOT_FOUND");
722 case SAP_PEER_AGENT_FOUND_RESULT_TIMEDOUT:
723 LOGW("SAP_PEER_AGENT_FOUND_RESULT_TIMEDOUT");
726 case SAP_PEER_AGENT_FOUND_RESULT_INTERNAL_ERROR:
727 LOGW("SAP_PEER_AGENT_FOUND_RESULT_INTERNAL_ERROR");
736 _find_peer_agent(gpointer user_data)
738 sap_info_s *priv = (sap_info_s *)user_data;
739 sap_agent_find_peer_agent(priv->agent, _on_peer_agent_updated, priv);
744 static void on_agent_initialized(sap_agent_h agent,
745 sap_agent_initialized_result_e result,
749 case SAP_AGENT_INITIALIZED_RESULT_SUCCESS:
750 LOGD("agent is initialized");
752 priv_data.agent = agent;
754 sap_file_transfer_set_incoming_file_cb(agent, _on_receive_file_cb, NULL);
755 sap_agent_set_service_connection_requested_cb(agent, on_conn_req, NULL);
758 case SAP_AGENT_INITIALIZED_RESULT_DUPLICATED:
759 LOGE("duplicate registration");
761 case SAP_AGENT_INITIALIZED_RESULT_INVALID_ARGUMENTS:
762 LOGE("invalid arguments");
764 case SAP_AGENT_INITIALIZED_RESULT_INTERNAL_ERROR:
765 LOGE("internal sap error");
768 LOGE("unknown status (%d)", result);
773 static void on_agent_deinitialized(sap_agent_h agent,
774 sap_agent_deinitialized_result_e result,
777 LOGD("result of deinitialize : %d", result);
780 static void _on_device_status_changed(sap_device_status_e status,
781 sap_transport_type_e transport_type,
784 LOGD("%s, status :%d", __func__, status);
786 switch (transport_type) {
787 case SAP_TRANSPORT_TYPE_BT:
788 LOGD("transport_type (%d): bt", transport_type);
790 case SAP_TRANSPORT_TYPE_BLE:
791 LOGD("transport_type (%d): ble", transport_type);
793 case SAP_TRANSPORT_TYPE_TCP:
794 LOGD("transport_type (%d): tcp/ip", transport_type);
796 case SAP_TRANSPORT_TYPE_USB:
797 LOGD("transport_type (%d): usb", transport_type);
799 case SAP_TRANSPORT_TYPE_MOBILE:
800 LOGD("transport_type (%d): mobile", transport_type);
803 LOGE("unknown transport_type (%d)", transport_type);
808 case SAP_DEVICE_STATUS_DETACHED:
809 LOGD("device is not connected.");
811 case SAP_DEVICE_STATUS_ATTACHED:
812 LOGD("Attached calling find peer now");
813 g_idle_add(_find_peer_agent, &priv_data);
816 LOGE("unknown status (%d)", status);
821 gboolean agent_initialize()
826 result = sap_agent_initialize(priv_data.agent, ACCESSORY_SERVICE_PROFILE_ID, SAP_AGENT_ROLE_CONSUMER,
827 on_agent_initialized, NULL);
829 LOGD("SAP >>> getRegisteredServiceAgent() >>> %d", result);
830 } while (result != SAP_RESULT_SUCCESS);
835 gboolean initialize_sap(void)
837 sap_agent_h agent = NULL;
839 sap_agent_create(&agent);
841 priv_data.agent = agent;
845 sap_set_device_status_changed_cb(_on_device_status_changed, NULL);
850 void deinitialize_sap(void)
852 if (priv_data.agent) {
853 int ret = sap_agent_deinitialize(priv_data.agent, on_agent_deinitialized, NULL);
855 case SAP_RESULT_FAILURE:
856 LOGW("Failed to deinitialize");
858 case SAP_RESULT_SUCCESS:
859 LOGD("Succeed to deinitialize");
861 case SAP_RESULT_PERMISSION_DENIED:
862 LOGW("permission denied: deinitialize ");
865 LOGD("deinitialize : %d", ret);
869 sap_agent_destroy(priv_data.agent);
870 priv_data.agent = NULL;