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;
85 gboolean file_on_progress = 0;
86 static string incoming_file_name;
88 static int rec_file_cnt = 0;
89 static int total_file_count = 0;
91 static gboolean _send_json_data(JsonObject *obj)
93 JsonGenerator *j_generator = NULL;
94 JsonNode *j_node = NULL;
99 j_generator = json_generator_new();
100 if (j_generator == NULL) {
101 LOGE("Unable to json_generator_new");
105 j_node = json_node_new(JSON_NODE_OBJECT);
106 if (j_node == NULL) {
107 LOGE("Unable to json_node_new");
111 json_node_set_object(j_node, obj);
112 json_generator_set_root(j_generator, j_node);
114 data = json_generator_to_data(j_generator, &size);
116 LOGE("Unable to json_generator_to_data");
120 if (priv_data.socket) {
121 LOGD("Send JSON data : %s", data);
122 result = sap_socket_send_data(priv_data.socket, ACCESSORY_SERVICE_CHANNEL_ID, strlen(data), (void *)data);
130 json_node_free(j_node);
133 g_object_unref(j_generator);
135 return result ? FALSE : TRUE;
138 static void notify_sync_progress(unsigned int file_progress)
140 if (total_file_count == 0)
143 double total_progress = (((double)rec_file_cnt / (double)total_file_count) + (1.0/(double)total_file_count*file_progress/100))*100;
145 LOGI("(%2d / %2d), file progress : %3u%%, total progress : %3u%%", rec_file_cnt, total_file_count, file_progress, (unsigned int)total_progress);
146 char progress_str[32];
147 snprintf(progress_str, sizeof(progress_str), "%u", (unsigned int)total_progress);
148 send_message("sync_progress", progress_str);
151 static void _on_send_completed(sap_file_transaction_h file_transaction,
152 sap_ft_transfer_e result,
153 const char *file_path,
156 if (priv_data.file_socket) {
157 sap_file_transfer_destroy(file_transaction);
158 priv_data.file_socket = NULL;
161 if (result == SAP_FT_TRANSFER_SUCCESS) {
162 LOGI("Transfer Completed");
164 if (chmod(sticker_data.file_path.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
165 LOGE("Failed to change permission : %s. error : %s", sticker_data.file_path.c_str(), strerror(errno));
168 LOGI("Succeed to change permission : %s", sticker_data.file_path.c_str());
169 if (create_sticker_provider_handle() == STICKER_ERROR_NONE) {
170 insert_sticker_data(sticker_data.file_path.c_str(), sticker_data.keyword.c_str(), sticker_data.group.c_str(), sticker_data.description.c_str());
171 destroy_sticker_provider_handle();
173 if (unlink(sticker_data.file_path.c_str()) == -1)
174 LOGE("Failed to remove sticker file");
181 case (SAP_FT_TRANSFER_FAIL_CHANNEL_IO): {
182 LOGW("Channel IO Error.");
186 case (SAP_FT_TRANSFER_FAIL_FILE_IO): {
187 LOGW("File IO Error.");
191 case (SAP_FT_TRANSFER_FAIL_CMD_DROPPED):
193 LOGW("Transfer dropped.");
197 case (SAP_FT_TRANSFER_FAIL_PEER_UNRESPONSIVE):
199 LOGW("Peer Un Responsive.");
203 case (SAP_FT_TRANSFER_FAIL_PEER_CONN_LOST):
205 LOGW("Connection Lost.");
209 case (SAP_FT_TRANSFER_FAIL_PEER_CANCELLED):
211 LOGW("Peer Cancelled.");
215 case (SAP_FT_TRANSFER_FAIL_SPACE_NOT_AVAILABLE):
222 LOGW("Unknown Error");
227 file_on_progress = 0;
230 static void _on_sending_file_in_progress(sap_file_transaction_h file_transaction,
231 unsigned short int 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 int complete_flags = 0;
482 if (vconf_get_int(VCONFKEY_STICKER_SYNC_COMPLETE, &complete_flags) == 0) {
483 if (sticker_data.group == string("arsticker"))
484 complete_flags |= 0x1;
485 else if (sticker_data.group == string("bitmoji"))
486 complete_flags |= 0x2;
488 LOGD("sync complete flag : %x", complete_flags);
490 if (vconf_set_int(VCONFKEY_STICKER_SYNC_COMPLETE, complete_flags) == 0)
491 LOGD("Succeed to set sync complete");
493 LOGW("Fail to set sync complete");
496 LOGW("Failed to get sticker sync flags");
499 json_object_set_string_member(j_object, "result", "success");
502 if (_send_json_data(j_object) == FALSE)
503 LOGE("Failed to send message");
505 json_object_unref(j_object);
507 LOGW("unknown msg id : %s", msg_id.c_str());
511 g_error_free(err_msg);
514 g_object_unref(parser);
517 static void on_conn_req(sap_peer_agent_h peer_agent,
519 sap_service_connection_result_e result,
524 case SAP_CONNECTION_SUCCESS:
525 LOGI("Connection success");
526 priv_data.socket = socket;
527 sap_peer_agent_accept_service_connection(peer_agent);
528 sap_peer_agent_set_service_connection_terminated_cb(peer_agent, conn_terminated, &priv_data);
529 sap_socket_set_data_received_cb(socket, on_data_received, peer_agent);
531 case SAP_CONNECTION_ALREADY_EXIST:
532 priv_data.socket = socket;
533 LOGI("Connection Already Exist");
535 case SAP_CONNECTION_FAILURE_DEVICE_UNREACHABLE:
536 LOGW("Connection failure device unreachable");
538 case SAP_CONNECTION_FAILURE_INVALID_PEERAGENT:
539 LOGW("Connection failure invalid peer agent");
541 case SAP_CONNECTION_FAILURE_NETWORK:
542 LOGW("Connection failure network");
544 case SAP_CONNECTION_FAILURE_PEERAGENT_NO_RESPONSE:
545 LOGW("Connection failure peer agent no response");
547 case SAP_CONNECTION_FAILURE_PEERAGENT_REJECTED:
548 LOGW("Connection failure peer agent rejected");
550 case SAP_CONNECTION_FAILURE_UNKNOWN:
551 LOGW("Connection failure unknown");
554 LOGW("Connection failure. error code : %d", result);
560 _on_service_connection_created(sap_peer_agent_h peer_agent,
562 sap_service_connection_result_e result,
565 sap_info_s *priv = (sap_info_s *)user_data;
569 case SAP_CONNECTION_SUCCESS:
570 sap_peer_agent_set_service_connection_terminated_cb(priv->peer_agent,
574 sap_socket_set_data_received_cb(socket, on_data_received, peer_agent);
575 priv->socket = socket;
576 LOGI("Connection Established");
578 if (!pending_sync_request.mode.empty()) {
579 LOGD("[Request to sync sticker] mode: %s, category: %s, type : %s", pending_sync_request.mode.c_str(),
580 pending_sync_request.category.c_str(),
581 pending_sync_request.type.c_str());
583 request_sticker_data(pending_sync_request.mode.c_str(), pending_sync_request.category.c_str(), pending_sync_request.type.c_str());
584 pending_sync_request.mode.clear();
585 pending_sync_request.category.clear();
586 pending_sync_request.type.clear();
591 case SAP_CONNECTION_ALREADY_EXIST:
592 priv->socket = socket;
593 LOGI("Connection Already Exist");
596 case SAP_CONNECTION_FAILURE_DEVICE_UNREACHABLE:
597 LOGW("Connection Failure device unreachable");
600 case SAP_CONNECTION_FAILURE_INVALID_PEERAGENT:
601 LOGW("Connection Failure invalid peer agent");
604 case SAP_CONNECTION_FAILURE_NETWORK:
605 LOGW("Connection Failure network");
608 case SAP_CONNECTION_FAILURE_PEERAGENT_NO_RESPONSE:
609 LOGW("Connection Failure peer agent no response");
612 case SAP_CONNECTION_FAILURE_PEERAGENT_REJECTED:
613 LOGW("Connection Failure peer agent rejected");
616 case SAP_CONNECTION_FAILURE_UNKNOWN:
617 LOGW("Connection Failure peer agent unknown");
620 case SAP_CONNECTION_IN_PROGRESS:
621 LOGW("Connection in progress");
624 case SAP_CONNECTION_PEER_AGENT_NOT_SUPPORTED:
625 LOGW("Connection peer agent not supported");
631 _create_service_connection(gpointer user_data)
633 sap_info_s *priv = (sap_info_s *)user_data;
634 int result = sap_agent_request_service_connection(priv->agent,
636 _on_service_connection_created,
639 LOGD("request connection result : %d", result);
645 _on_peer_agent_updated(sap_peer_agent_h peer_agent,
646 sap_peer_agent_status_e peer_status,
647 sap_peer_agent_found_result_e result,
650 sap_info_s *priv = (sap_info_s *)user_data;
654 case SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED:
655 LOGW("SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED");
658 case SAP_PEER_AGENT_FOUND_RESULT_FOUND:
659 if (peer_status == SAP_PEER_AGENT_STATUS_AVAILABLE)
661 LOGD("SAP_PEER_AGENT_FOUND_RESULT_FOUND");
662 priv->peer_agent = peer_agent;
663 g_idle_add(_create_service_connection, priv);
667 sap_peer_agent_destroy(peer_agent);
671 case SAP_PEER_AGENT_FOUND_RESULT_SERVICE_NOT_FOUND:
672 LOGW("SAP_PEER_AGENT_FOUND_RESULT_SERVICE_NOT_FOUND");
675 case SAP_PEER_AGENT_FOUND_RESULT_TIMEDOUT:
676 LOGW("SAP_PEER_AGENT_FOUND_RESULT_TIMEDOUT");
679 case SAP_PEER_AGENT_FOUND_RESULT_INTERNAL_ERROR:
680 LOGW("SAP_PEER_AGENT_FOUND_RESULT_INTERNAL_ERROR");
689 _find_peer_agent(gpointer user_data)
691 sap_info_s *priv = (sap_info_s *)user_data;
692 sap_agent_find_peer_agent(priv->agent, _on_peer_agent_updated, priv);
697 static void on_agent_initialized(sap_agent_h agent,
698 sap_agent_initialized_result_e result,
702 case SAP_AGENT_INITIALIZED_RESULT_SUCCESS:
703 LOGD("agent is initialized");
705 priv_data.agent = agent;
707 sap_file_transfer_set_incoming_file_cb(agent, _on_receive_file_cb, NULL);
708 sap_agent_set_service_connection_requested_cb(agent, on_conn_req, NULL);
711 case SAP_AGENT_INITIALIZED_RESULT_DUPLICATED:
712 LOGE("duplicate registration");
714 case SAP_AGENT_INITIALIZED_RESULT_INVALID_ARGUMENTS:
715 LOGE("invalid arguments");
717 case SAP_AGENT_INITIALIZED_RESULT_INTERNAL_ERROR:
718 LOGE("internal sap error");
721 LOGE("unknown status (%d)", result);
726 static void on_agent_deinitialized(sap_agent_h agent,
727 sap_agent_deinitialized_result_e result,
730 LOGD("result of deinitialize : %d", result);
733 static void _on_device_status_changed(sap_device_status_e status,
734 sap_transport_type_e transport_type,
737 LOGD("%s, status :%d", __func__, status);
739 switch (transport_type) {
740 case SAP_TRANSPORT_TYPE_BT:
741 LOGD("transport_type (%d): bt", transport_type);
743 case SAP_TRANSPORT_TYPE_BLE:
744 LOGD("transport_type (%d): ble", transport_type);
746 case SAP_TRANSPORT_TYPE_TCP:
747 LOGD("transport_type (%d): tcp/ip", transport_type);
749 case SAP_TRANSPORT_TYPE_USB:
750 LOGD("transport_type (%d): usb", transport_type);
752 case SAP_TRANSPORT_TYPE_MOBILE:
753 LOGD("transport_type (%d): mobile", transport_type);
756 LOGE("unknown transport_type (%d)", transport_type);
761 case SAP_DEVICE_STATUS_DETACHED:
762 LOGD("device is not connected.");
764 case SAP_DEVICE_STATUS_ATTACHED:
765 LOGD("Attached calling find peer now");
766 g_idle_add(_find_peer_agent, &priv_data);
769 LOGE("unknown status (%d)", status);
774 gboolean agent_initialize()
779 result = sap_agent_initialize(priv_data.agent, ACCESSORY_SERVICE_PROFILE_ID, SAP_AGENT_ROLE_CONSUMER,
780 on_agent_initialized, NULL);
782 LOGD("SAP >>> getRegisteredServiceAgent() >>> %d", result);
783 } while (result != SAP_RESULT_SUCCESS);
788 gboolean initialize_sap(void)
790 sap_agent_h agent = NULL;
792 sap_agent_create(&agent);
794 priv_data.agent = agent;
798 sap_set_device_status_changed_cb(_on_device_status_changed, NULL);
803 void deinitialize_sap(void)
805 if (priv_data.agent) {
806 int ret = sap_agent_deinitialize(priv_data.agent, on_agent_deinitialized, NULL);
808 case SAP_RESULT_FAILURE:
809 LOGW("Failed to deinitialize");
811 case SAP_RESULT_SUCCESS:
812 LOGD("Succeed to deinitialize");
814 case SAP_RESULT_PERMISSION_DENIED:
815 LOGW("permission denied: deinitialize ");
818 LOGD("deinitialize : %d", ret);
822 sap_agent_destroy(priv_data.agent);
823 priv_data.agent = NULL;